From da1586461e53a4dd045738cce309ab488970f0ef Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 2 Oct 2012 22:34:04 -0400 Subject: pch_gbe: Fix PTP dependencies. The config combination: CONFIG_PCH_GBE=y CONFIG_PCH_PTP=y CONFIG_PTP_1588_CLOCK=m doesn't work, because then you have a built-in kernel object (the PCH_PTP code) referring to symbols in a module (PTP_1588_CLOCK). Fix this like IXGBE, by using "select PTP_1588_CLOCK" instead of a "depends on". Reported-by: Haicheng Li Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index bce0164..9730241 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -26,7 +26,7 @@ if PCH_GBE config PCH_PTP bool "PCH PTP clock support" default n - depends on PTP_1588_CLOCK_PCH + select PTP_1588_CLOCK_PCH ---help--- Say Y here if you want to use Precision Time Protocol (PTP) in the driver. PTP is a method to precisely synchronize distributed clocks -- cgit v0.10.2 From ffb5ba90017505a19e238e986e6d33f09e4df765 Mon Sep 17 00:00:00 2001 From: htbegin Date: Mon, 1 Oct 2012 16:42:43 +0000 Subject: net: ethernet: davinci_cpdma: decrease the desc count when cleaning up the remaining packets chan->count is used by rx channel. If the desc count is not updated by the clean up loop in cpdma_chan_stop, the value written to the rxfree register in cpdma_chan_start will be incorrect. Signed-off-by: Tao Hou Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index d15c888..4995673 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -863,6 +863,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) next_dma = desc_read(desc, hw_next); chan->head = desc_from_phys(pool, next_dma); + chan->count--; chan->stats.teardown_dequeue++; /* issue callback without locks held */ -- cgit v0.10.2 From 62b54dd91567686a1cb118f76a72d5f4764a86dd Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Mon, 1 Oct 2012 23:19:14 +0000 Subject: ipv6: don't add link local route when there is no link local address When an address is added on loopback (ip -6 a a 2002::1/128 dev lo), a route to fe80::/64 is added in the main table: unreachable fe80::/64 dev lo proto kernel metric 256 error -101 This route does not match any prefix (no fe80:: address on lo). In fact, addrconf_dev_config() will not add link local address because this function filters interfaces by type. If the link local address is added manually, the route to the link local prefix will be automatically added by addrconf_add_linklocal(). Note also, that this route is not deleted when the address is removed. After looking at the code, it seems that addrconf_add_lroute() is redundant with addrconf_add_linklocal(), because this function will add the link local route when the link local address is configured. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 480e684..d7c56f8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1769,14 +1769,6 @@ static void sit_route_add(struct net_device *dev) } #endif -static void addrconf_add_lroute(struct net_device *dev) -{ - struct in6_addr addr; - - ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); - addrconf_prefix_route(&addr, 64, dev, 0, 0); -} - static struct inet6_dev *addrconf_add_dev(struct net_device *dev) { struct inet6_dev *idev; @@ -1794,8 +1786,6 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) if (!(dev->flags & IFF_LOOPBACK)) addrconf_add_mroute(dev); - /* Add link local route */ - addrconf_add_lroute(dev); return idev; } @@ -2474,10 +2464,9 @@ static void addrconf_sit_config(struct net_device *dev) sit_add_v4_addrs(idev); - if (dev->flags&IFF_POINTOPOINT) { + if (dev->flags&IFF_POINTOPOINT) addrconf_add_mroute(dev); - addrconf_add_lroute(dev); - } else + else sit_route_add(dev); } #endif -- cgit v0.10.2 From 786fdf0bbf1c3a1b402bb2da946b93e0b36a8f32 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Oct 2012 01:47:46 +0000 Subject: bnx2x: use strlcpy() to copy a string DRV_MODULE_VERSION is smaller than the ->version buffer so the memcpy() copies 1 byte past the end of the string. It's not super harmful, but it makes the static checkers complain. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f7ed122..d5648fc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -3052,9 +3052,8 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp) struct eth_stats_info *ether_stat = &bp->slowpath->drv_info_to_mcp.ether_stat; - /* leave last char as NULL */ - memcpy(ether_stat->version, DRV_MODULE_VERSION, - ETH_STAT_INFO_VERSION_LEN - 1); + strlcpy(ether_stat->version, DRV_MODULE_VERSION, + ETH_STAT_INFO_VERSION_LEN); bp->sp_objs[0].mac_obj.get_n_elements(bp, &bp->sp_objs[0].mac_obj, DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED, -- cgit v0.10.2 From 5316cf9a5197eb80b2800e1acadde287924ca975 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 2 Oct 2012 06:14:17 +0000 Subject: 8021q: fix mac_len recomputation in vlan_untag() skb_reset_mac_len() relies on the value of the skb->network_header pointer, therefore we must wait for such pointer to be recalculated before computing the new mac_len value. Signed-off-by: Antonio Quartulli Signed-off-by: David S. Miller diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index b258da8..add69d0 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -105,7 +105,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) return NULL; memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); skb->mac_header += VLAN_HLEN; - skb_reset_mac_len(skb); return skb; } @@ -139,6 +138,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) skb_reset_network_header(skb); skb_reset_transport_header(skb); + skb_reset_mac_len(skb); + return skb; err_free: -- cgit v0.10.2 From 864499449f256e32815575a9b860267ebefa6d70 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 2 Oct 2012 20:31:14 -0700 Subject: tg3: Fix sparse warnings. drivers/net/ethernet/broadcom/tg3.c:8121:8: warning: symbol 'i' shadows an earlier one drivers/net/ethernet/broadcom/tg3.c:8003:6: originally declared here drivers/net/ethernet/broadcom/tg3.c:785:5: warning: symbol 'tg3_ape_scratchpad_read' was not declared. Should it be static? drivers/net/ethernet/broadcom/tg3.c:7781:19: warning: Using plain integer as NULL pointer drivers/net/ethernet/broadcom/tg3.c:10231:31: error: bad constant expression Reported-by: Fengguang Wu Signed-off-by: Michael Chan Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 46280ba..a8800ac 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -782,7 +782,8 @@ static int tg3_ape_wait_for_event(struct tg3 *tp, u32 timeout_us) return i == timeout_us / 10; } -int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, u32 len) +static int tg3_ape_scratchpad_read(struct tg3 *tp, u32 *data, u32 base_off, + u32 len) { int err; u32 i, bufoff, msgoff, maxlen, apedata; @@ -7763,7 +7764,7 @@ static int tg3_alloc_consistent(struct tg3 *tp) sblk = tnapi->hw_status; if (tg3_flag(tp, ENABLE_RSS)) { - u16 *prodptr = 0; + u16 *prodptr = NULL; /* * When RSS is enabled, the status block format changes @@ -8103,11 +8104,11 @@ static int tg3_chip_reset(struct tg3 *tp) u16 val16; if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) { - int i; + int j; u32 cfg_val; /* Wait for link training to complete. */ - for (i = 0; i < 5000; i++) + for (j = 0; j < 5000; j++) udelay(100); pci_read_config_dword(tp->pdev, 0xc4, &cfg_val); @@ -10206,7 +10207,7 @@ static u32 tg3_irq_count(struct tg3 *tp) static bool tg3_enable_msix(struct tg3 *tp) { int i, rc; - struct msix_entry msix_ent[tp->irq_max]; + struct msix_entry msix_ent[TG3_IRQ_MAX_VECS]; tp->txq_cnt = tp->txq_req; tp->rxq_cnt = tp->rxq_req; -- cgit v0.10.2 From 8208367371b7f581dd13fe8bf28f8d7f17f4bf32 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Wed, 1 Aug 2012 07:12:25 +0000 Subject: ixgbe: Fix PTP X540 SDP alignment code for PPS signal This patch fixes a bug in the method used for calculating the trigger alignment for SDP0 when enabling a PPS output on the X540. The alignment math wasn't properly taking into account the overflow cyclecounter, and was misaligning the pin triggers so that two X540 devices synced properly had mis-aligned SDP pins. This patch fixes the math to calculate the correct seconds alignment for the PPS signal. Signed-off-by: Jacob Keller Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 39881cb..58d930d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -106,6 +106,94 @@ static struct sock_filter ptp_filter[] = { }; /** + * ixgbe_ptp_enable_sdp + * @hw: the hardware private structure + * @shift: the clock shift for calculating nanoseconds + * + * this function enables the clock out feature on the sdp0 for the + * X540 device. It will create a 1second periodic output that can be + * used as the PPS (via an interrupt). + * + * It calculates when the systime will be on an exact second, and then + * aligns the start of the PPS signal to that value. The shift is + * necessary because it can change based on the link speed. + */ +static void ixgbe_ptp_enable_sdp(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + int shift = adapter->cc.shift; + u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem; + u64 ns = 0, clock_edge = 0; + + switch (hw->mac.type) { + case ixgbe_mac_X540: + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); + + /* + * enable the SDP0 pin as output, and connected to the native + * function for Timesync (ClockOut) + */ + esdp |= (IXGBE_ESDP_SDP0_DIR | + IXGBE_ESDP_SDP0_NATIVE); + + /* + * enable the Clock Out feature on SDP0, and allow interrupts + * to occur when the pin changes + */ + tsauxc = (IXGBE_TSAUXC_EN_CLK | + IXGBE_TSAUXC_SYNCLK | + IXGBE_TSAUXC_SDP0_INT); + + /* clock period (or pulse length) */ + clktiml = (u32)(NSECS_PER_SEC << shift); + clktimh = (u32)((NSECS_PER_SEC << shift) >> 32); + + /* + * Account for the cyclecounter wrap-around value by + * using the converted ns value of the current time to + * check for when the next aligned second would occur. + */ + clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML); + clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; + ns = timecounter_cyc2time(&adapter->tc, clock_edge); + + div_u64_rem(ns, NSECS_PER_SEC, &rem); + clock_edge += ((NSECS_PER_SEC - (u64)rem) << shift); + + /* specify the initial clock start time */ + trgttiml = (u32)clock_edge; + trgttimh = (u32)(clock_edge >> 32); + + IXGBE_WRITE_REG(hw, IXGBE_CLKTIML, clktiml); + IXGBE_WRITE_REG(hw, IXGBE_CLKTIMH, clktimh); + IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml); + IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh); + + IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); + + IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_TIMESYNC); + IXGBE_WRITE_FLUSH(hw); + break; + default: + break; + } +} + +/** + * ixgbe_ptp_disable_sdp + * @hw: the private hardware structure + * + * this function disables the auxiliary SDP clock out feature + */ +static void ixgbe_ptp_disable_sdp(struct ixgbe_hw *hw) +{ + IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TIMESYNC); + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0); + IXGBE_WRITE_FLUSH(hw); +} + +/** * ixgbe_ptp_read - read raw cycle counter (to be used by time counter) * @cc: the cyclecounter structure * @@ -187,6 +275,7 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) unsigned long flags; u64 now; + ixgbe_ptp_disable_sdp(&adapter->hw); spin_lock_irqsave(&adapter->tmreg_lock, flags); now = timecounter_read(&adapter->tc); @@ -198,6 +287,8 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) now); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + ixgbe_ptp_enable_sdp(adapter); + return 0; } @@ -246,11 +337,14 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, ns = ts->tv_sec * 1000000000ULL; ns += ts->tv_nsec; + ixgbe_ptp_disable_sdp(&adapter->hw); + /* reset the timecounter */ spin_lock_irqsave(&adapter->tmreg_lock, flags); timecounter_init(&adapter->tc, &adapter->cc, ns); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + ixgbe_ptp_enable_sdp(adapter); return 0; } @@ -323,91 +417,6 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) } } -/** - * ixgbe_ptp_enable_sdp - * @hw: the hardware private structure - * @shift: the clock shift for calculating nanoseconds - * - * this function enables the clock out feature on the sdp0 for the - * X540 device. It will create a 1second periodic output that can be - * used as the PPS (via an interrupt). - * - * It calculates when the systime will be on an exact second, and then - * aligns the start of the PPS signal to that value. The shift is - * necessary because it can change based on the link speed. - */ -static void ixgbe_ptp_enable_sdp(struct ixgbe_hw *hw, int shift) -{ - u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh; - u64 clock_edge = 0; - u32 rem; - - switch (hw->mac.type) { - case ixgbe_mac_X540: - esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); - - /* - * enable the SDP0 pin as output, and connected to the native - * function for Timesync (ClockOut) - */ - esdp |= (IXGBE_ESDP_SDP0_DIR | - IXGBE_ESDP_SDP0_NATIVE); - - /* - * enable the Clock Out feature on SDP0, and allow interrupts - * to occur when the pin changes - */ - tsauxc = (IXGBE_TSAUXC_EN_CLK | - IXGBE_TSAUXC_SYNCLK | - IXGBE_TSAUXC_SDP0_INT); - - /* clock period (or pulse length) */ - clktiml = (u32)(NSECS_PER_SEC << shift); - clktimh = (u32)((NSECS_PER_SEC << shift) >> 32); - - clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIML); - clock_edge |= (u64)IXGBE_READ_REG(hw, IXGBE_SYSTIMH) << 32; - - /* - * account for the fact that we can't do u64 division - * with remainder, by converting the clock values into - * nanoseconds first - */ - clock_edge >>= shift; - div_u64_rem(clock_edge, NSECS_PER_SEC, &rem); - clock_edge += (NSECS_PER_SEC - rem); - clock_edge <<= shift; - - /* specify the initial clock start time */ - trgttiml = (u32)clock_edge; - trgttimh = (u32)(clock_edge >> 32); - - IXGBE_WRITE_REG(hw, IXGBE_CLKTIML, clktiml); - IXGBE_WRITE_REG(hw, IXGBE_CLKTIMH, clktimh); - IXGBE_WRITE_REG(hw, IXGBE_TRGTTIML0, trgttiml); - IXGBE_WRITE_REG(hw, IXGBE_TRGTTIMH0, trgttimh); - - IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); - IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); - - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_TIMESYNC); - break; - default: - break; - } -} - -/** - * ixgbe_ptp_disable_sdp - * @hw: the private hardware structure - * - * this function disables the auxiliary SDP clock out feature - */ -static void ixgbe_ptp_disable_sdp(struct ixgbe_hw *hw) -{ - IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TIMESYNC); - IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0); -} /** * ixgbe_ptp_overflow_check - delayed work to detect SYSTIME overflow @@ -877,10 +886,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000); IXGBE_WRITE_FLUSH(hw); - /* now that the shift has been calculated and the systime - * registers reset, (re-)enable the Clock out feature*/ - ixgbe_ptp_enable_sdp(hw, shift); - /* store the new cycle speed */ adapter->cycle_speed = cycle_speed; @@ -901,6 +906,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) ktime_to_ns(ktime_get_real())); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + + /* Now that the shift has been calculated and the systime + * registers reset, (re-)enable the Clock out feature + */ + ixgbe_ptp_enable_sdp(adapter); } /** -- cgit v0.10.2 From db0677fa29862d29e9956980d9fab43c52179e34 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 24 Aug 2012 07:46:54 +0000 Subject: ixgbe: (PTP) Fix PPS interrupt code Driver was enabling PPS interrupt even when user wasn't enabling it via the ptp core. This patch fixes the PPS so that it is only enabled explicitly, and moves the interrupt enabling code into the correct location in the driver Signed-off-by: Jacob Keller Cc: Stable [3.5] Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 868af69..c407b2f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2322,6 +2322,12 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, default: break; } + +#ifdef CONFIG_IXGBE_PTP + if (adapter->hw.mac.type == ixgbe_mac_X540) + mask |= IXGBE_EIMS_TIMESYNC; +#endif + if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT)) mask |= IXGBE_EIMS_FLOW_DIR; @@ -2385,8 +2391,10 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) } ixgbe_check_fan_failure(adapter, eicr); + #ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_check_pps_event(adapter, eicr); + if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) + ixgbe_ptp_check_pps_event(adapter, eicr); #endif /* re-enable the original interrupt state, no lsc, no queues */ @@ -2580,7 +2588,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data) ixgbe_check_fan_failure(adapter, eicr); #ifdef CONFIG_IXGBE_PTP - ixgbe_ptp_check_pps_event(adapter, eicr); + if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) + ixgbe_ptp_check_pps_event(adapter, eicr); #endif /* would disable interrupts here but EIAM disabled it */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 58d930d..d929131 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c @@ -106,39 +106,43 @@ static struct sock_filter ptp_filter[] = { }; /** - * ixgbe_ptp_enable_sdp + * ixgbe_ptp_setup_sdp * @hw: the hardware private structure - * @shift: the clock shift for calculating nanoseconds * - * this function enables the clock out feature on the sdp0 for the - * X540 device. It will create a 1second periodic output that can be - * used as the PPS (via an interrupt). + * this function enables or disables the clock out feature on SDP0 for + * the X540 device. It will create a 1second periodic output that can + * be used as the PPS (via an interrupt). * * It calculates when the systime will be on an exact second, and then * aligns the start of the PPS signal to that value. The shift is * necessary because it can change based on the link speed. */ -static void ixgbe_ptp_enable_sdp(struct ixgbe_adapter *adapter) +static void ixgbe_ptp_setup_sdp(struct ixgbe_adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; int shift = adapter->cc.shift; u32 esdp, tsauxc, clktiml, clktimh, trgttiml, trgttimh, rem; u64 ns = 0, clock_edge = 0; - switch (hw->mac.type) { - case ixgbe_mac_X540: + if ((adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED) && + (hw->mac.type == ixgbe_mac_X540)) { + + /* disable the pin first */ + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); + IXGBE_WRITE_FLUSH(hw); + esdp = IXGBE_READ_REG(hw, IXGBE_ESDP); /* - * enable the SDP0 pin as output, and connected to the native - * function for Timesync (ClockOut) + * enable the SDP0 pin as output, and connected to the + * native function for Timesync (ClockOut) */ esdp |= (IXGBE_ESDP_SDP0_DIR | IXGBE_ESDP_SDP0_NATIVE); /* - * enable the Clock Out feature on SDP0, and allow interrupts - * to occur when the pin changes + * enable the Clock Out feature on SDP0, and allow + * interrupts to occur when the pin changes */ tsauxc = (IXGBE_TSAUXC_EN_CLK | IXGBE_TSAUXC_SYNCLK | @@ -171,25 +175,10 @@ static void ixgbe_ptp_enable_sdp(struct ixgbe_adapter *adapter) IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp); IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, tsauxc); - - IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_TIMESYNC); - IXGBE_WRITE_FLUSH(hw); - break; - default: - break; + } else { + IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0x0); } -} -/** - * ixgbe_ptp_disable_sdp - * @hw: the private hardware structure - * - * this function disables the auxiliary SDP clock out feature - */ -static void ixgbe_ptp_disable_sdp(struct ixgbe_hw *hw) -{ - IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_TIMESYNC); - IXGBE_WRITE_REG(hw, IXGBE_TSAUXC, 0); IXGBE_WRITE_FLUSH(hw); } @@ -275,7 +264,6 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) unsigned long flags; u64 now; - ixgbe_ptp_disable_sdp(&adapter->hw); spin_lock_irqsave(&adapter->tmreg_lock, flags); now = timecounter_read(&adapter->tc); @@ -287,7 +275,8 @@ static int ixgbe_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) now); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); - ixgbe_ptp_enable_sdp(adapter); + + ixgbe_ptp_setup_sdp(adapter); return 0; } @@ -337,14 +326,12 @@ static int ixgbe_ptp_settime(struct ptp_clock_info *ptp, ns = ts->tv_sec * 1000000000ULL; ns += ts->tv_nsec; - ixgbe_ptp_disable_sdp(&adapter->hw); - /* reset the timecounter */ spin_lock_irqsave(&adapter->tmreg_lock, flags); timecounter_init(&adapter->tc, &adapter->cc, ns); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); - ixgbe_ptp_enable_sdp(adapter); + ixgbe_ptp_setup_sdp(adapter); return 0; } @@ -375,8 +362,9 @@ static int ixgbe_ptp_enable(struct ptp_clock_info *ptp, if (on) adapter->flags2 |= IXGBE_FLAG2_PTP_PPS_ENABLED; else - adapter->flags2 &= - ~IXGBE_FLAG2_PTP_PPS_ENABLED; + adapter->flags2 &= ~IXGBE_FLAG2_PTP_PPS_ENABLED; + + ixgbe_ptp_setup_sdp(adapter); return 0; default: break; @@ -399,21 +387,12 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr) struct ixgbe_hw *hw = &adapter->hw; struct ptp_clock_event event; - event.type = PTP_CLOCK_PPS; - - /* Make sure ptp clock is valid, and PPS event enabled */ - if (!adapter->ptp_clock || - !(adapter->flags2 & IXGBE_FLAG2_PTP_PPS_ENABLED)) - return; - - if (unlikely(eicr & IXGBE_EICR_TIMESYNC)) { - switch (hw->mac.type) { - case ixgbe_mac_X540: - ptp_clock_event(adapter->ptp_clock, &event); - break; - default: - break; - } + switch (hw->mac.type) { + case ixgbe_mac_X540: + ptp_clock_event(adapter->ptp_clock, &event); + break; + default: + break; } } @@ -831,9 +810,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) if (adapter->cycle_speed == cycle_speed && timinca) return; - /* disable the SDP clock out */ - ixgbe_ptp_disable_sdp(hw); - /** * Scale the NIC cycle counter by a large factor so that * relatively small corrections to the frequency can be added @@ -907,10 +883,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter) spin_unlock_irqrestore(&adapter->tmreg_lock, flags); - /* Now that the shift has been calculated and the systime + /* + * Now that the shift has been calculated and the systime * registers reset, (re-)enable the Clock out feature */ - ixgbe_ptp_enable_sdp(adapter); + ixgbe_ptp_setup_sdp(adapter); } /** @@ -989,10 +966,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter) */ void ixgbe_ptp_stop(struct ixgbe_adapter *adapter) { - ixgbe_ptp_disable_sdp(&adapter->hw); - /* stop the overflow check task */ - adapter->flags2 &= ~IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED; + adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED | + IXGBE_FLAG2_PTP_PPS_ENABLED); + + ixgbe_ptp_setup_sdp(adapter); if (adapter->ptp_clock) { ptp_clock_unregister(adapter->ptp_clock); -- cgit v0.10.2 From 1cc92eb871d6cbb1da038b4bcd89eec3c73b9781 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 21 Sep 2012 07:23:20 +0000 Subject: ixgbe: fix PTP ethtool timestamping function This patch fixes a development issue that occurred due to invalid modes reported in the ethtool get_ts_info function. The issue is resolved by removing unsupported modes from the Rx supported list. CC: stable [3.5] Signed-off-by: Jacob Keller Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 4104ea25..56b20d1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2690,10 +2690,7 @@ static int ixgbe_get_ts_info(struct net_device *dev, (1 << HWTSTAMP_FILTER_NONE) | (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | - (1 << HWTSTAMP_FILTER_SOME); + (1 << HWTSTAMP_FILTER_PTP_V2_EVENT); break; #endif /* CONFIG_IXGBE_PTP */ default: -- cgit v0.10.2 From 4a97df0bfaa8c0c1cd057cb8f1030a71cb4d8832 Mon Sep 17 00:00:00 2001 From: Emil Tantilov Date: Thu, 20 Sep 2012 03:33:51 +0000 Subject: ixgbe: fix poll loop for FDIRCTRL.INIT_DONE bit The loop in ixgbe_reinit_fdir_tables_82599() only polls for up to 100us resulting in failures to update the FDIR filter table at 1Gbps and 10Gbps when under load. The poll times for FDIRCTRL.INIT_DONE are 55us, 550us and 5.5ms for 10Gbps, 1Gbps and 100Mbps respectively. This patch sets the wait time to be the same as in ixgbe_fdir_enable_82599() Reported-by: Bhushan Signed-off-by: Emil Tantilov Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c index 18bf08c..1077cb2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c @@ -1099,7 +1099,7 @@ s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw) if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) & IXGBE_FDIRCTRL_INIT_DONE) break; - udelay(10); + usleep_range(1000, 2000); } if (i >= IXGBE_FDIR_INIT_DONE_POLL) { hw_dbg(hw, "Flow Director Signature poll time exceeded!\n"); -- cgit v0.10.2 From df376f0de167754da9b3ece4afdb5bb8bf3fbf3e Mon Sep 17 00:00:00 2001 From: "joshua.a.hay@intel.com" Date: Fri, 21 Sep 2012 00:08:21 +0000 Subject: ixgbe: add support for X540-AT1 This patch adds device support for Ethernet Controller X540-AT1. Signed-off-by: Josh Hay Tested-by: Phil Schmitt Signed-off-by: Jeff Kirsher diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 90e41db..dbf37e4 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -70,6 +70,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index c407b2f..fa3d552 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -114,6 +114,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 }, /* required last entry */ {0, } }; @@ -7054,6 +7055,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id, is_wol_supported = 1; break; case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: /* check eeprom to see if enabled wol */ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) && diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 400f86a..0722f33 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -65,6 +65,7 @@ #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 #define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A +#define IXGBE_DEV_ID_X540T1 0x1560 /* VF Device IDs */ #define IXGBE_DEV_ID_82599_VF 0x10ED -- cgit v0.10.2 From 8c357ebd5693b95ca6bb21242838ca3738a68450 Mon Sep 17 00:00:00 2001 From: Vipul Pandya Date: Wed, 3 Oct 2012 03:22:32 +0000 Subject: cxgb4: Dynamically allocate memory in t4_memory_rw() and get_vpd_params() This patch changes memory allocation to reduce stack footprint Signed-off-by: Jay Hernandez Signed-off-by: Vipul Pandya Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 35b81d8..137a244 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -408,7 +408,8 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, __be32 *buf, int dir) { u32 pos, start, end, offset, memoffset; - int ret; + int ret = 0; + __be32 *data; /* * Argument sanity checks ... @@ -416,6 +417,10 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, if ((addr & 0x3) || (len & 0x3)) return -EINVAL; + data = vmalloc(MEMWIN0_APERTURE/sizeof(__be32)); + if (!data) + return -ENOMEM; + /* * Offset into the region of memory which is being accessed * MEM_EDC0 = 0 @@ -438,7 +443,6 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, offset = (addr - start)/sizeof(__be32); for (pos = start; pos < end; pos += MEMWIN0_APERTURE, offset = 0) { - __be32 data[MEMWIN0_APERTURE/sizeof(__be32)]; /* * If we're writing, copy the data from the caller's memory @@ -452,7 +456,7 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, if (offset || len < MEMWIN0_APERTURE) { ret = t4_mem_win_rw(adap, pos, data, 1); if (ret) - return ret; + break; } while (offset < (MEMWIN0_APERTURE/sizeof(__be32)) && len > 0) { @@ -466,7 +470,7 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, */ ret = t4_mem_win_rw(adap, pos, data, dir); if (ret) - return ret; + break; /* * If we're reading, copy the data into the caller's memory @@ -480,7 +484,8 @@ static int t4_memory_rw(struct adapter *adap, int mtype, u32 addr, u32 len, } } - return 0; + vfree(data); + return ret; } int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len, @@ -519,16 +524,21 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) u32 cclk_param, cclk_val; int i, ret; int ec, sn; - u8 vpd[VPD_LEN], csum; + u8 *vpd, csum; unsigned int vpdr_len, kw_offset, id_len; - ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(vpd), vpd); + vpd = vmalloc(VPD_LEN); + if (!vpd) + return -ENOMEM; + + ret = pci_read_vpd(adapter->pdev, VPD_BASE, VPD_LEN, vpd); if (ret < 0) - return ret; + goto out; if (vpd[0] != PCI_VPD_LRDT_ID_STRING) { dev_err(adapter->pdev_dev, "missing VPD ID string\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } id_len = pci_vpd_lrdt_size(vpd); @@ -538,21 +548,24 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) i = pci_vpd_find_tag(vpd, 0, VPD_LEN, PCI_VPD_LRDT_RO_DATA); if (i < 0) { dev_err(adapter->pdev_dev, "missing VPD-R section\n"); - return -EINVAL; + ret = -EINVAL; + goto out; } vpdr_len = pci_vpd_lrdt_size(&vpd[i]); kw_offset = i + PCI_VPD_LRDT_TAG_SIZE; if (vpdr_len + kw_offset > VPD_LEN) { dev_err(adapter->pdev_dev, "bad VPD-R length %u\n", vpdr_len); - return -EINVAL; + ret = -EINVAL; + goto out; } #define FIND_VPD_KW(var, name) do { \ var = pci_vpd_find_info_keyword(vpd, kw_offset, vpdr_len, name); \ if (var < 0) { \ dev_err(adapter->pdev_dev, "missing VPD keyword " name "\n"); \ - return -EINVAL; \ + ret = -EINVAL; \ + goto out; \ } \ var += PCI_VPD_INFO_FLD_HDR_SIZE; \ } while (0) @@ -564,7 +577,8 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) if (csum) { dev_err(adapter->pdev_dev, "corrupted VPD EEPROM, actual csum %u\n", csum); - return -EINVAL; + ret = -EINVAL; + goto out; } FIND_VPD_KW(ec, "EC"); @@ -587,6 +601,9 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK)); ret = t4_query_params(adapter, adapter->mbox, 0, 0, 1, &cclk_param, &cclk_val); + +out: + vfree(vpd); if (ret) return ret; p->cclk = cclk_val; -- cgit v0.10.2 From 065f8b9210b46c49b578d188ce8b8ee240a55777 Mon Sep 17 00:00:00 2001 From: Yuval Mintz Date: Wed, 3 Oct 2012 04:22:59 +0000 Subject: bnx2x: fix ring size for 10G functions Commit d760fc37b0f74502b3f748951f22c6683b079a8e caused 1G functions to allocate rx rings which were 1/10 of the size of 10G functions' rx rings. However, it also caused 10G functions on 5771x boards to allocate small rings, which limits their possible (default) rx throughput. This patch causes all 10G functions to use rings of intended length by default. Signed-off-by: Yuval Mintz Signed-off-by: Ariel Elior Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 30f04a3..2422099 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -3523,15 +3523,18 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index) } else #endif if (!bp->rx_ring_size) { - u32 cfg = SHMEM_RD(bp, - dev_info.port_hw_config[BP_PORT(bp)].default_cfg); - rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp); - /* Dercease ring size for 1G functions */ - if ((cfg & PORT_HW_CFG_NET_SERDES_IF_MASK) == - PORT_HW_CFG_NET_SERDES_IF_SGMII) - rx_ring_size /= 10; + if (CHIP_IS_E3(bp)) { + u32 cfg = SHMEM_RD(bp, + dev_info.port_hw_config[BP_PORT(bp)]. + default_cfg); + + /* Decrease ring size for 1G functions */ + if ((cfg & PORT_HW_CFG_NET_SERDES_IF_MASK) == + PORT_HW_CFG_NET_SERDES_IF_SGMII) + rx_ring_size /= 10; + } /* allocate at least number of buffers required by FW */ rx_ring_size = max_t(int, bp->disable_tpa ? MIN_RX_SIZE_NONTPA : -- cgit v0.10.2 From c0b8b99287235626a5850ef7e5bfc842d1ebcecd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 3 Oct 2012 20:50:08 -0400 Subject: cxgb4: Fix build error due to missing linux/vmalloc.h include. Reported-by: Stephen Rothwell Signed-off-by: David S. Miller diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 745a1f5..31752b2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "cxgb4_uld.h" #include "t4_hw.h" -- cgit v0.10.2 From 4a4bfdcd29572864a561f64a09af9ff444f3cd41 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 3 Oct 2012 18:17:54 +0200 Subject: can: peak_pci: fix error return code Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Peter Senna Tschudin Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index f0a1296..f5b82ae 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -583,12 +583,14 @@ static int __devinit peak_pci_probe(struct pci_dev *pdev, cfg_base = pci_iomap(pdev, 0, PEAK_PCI_CFG_SIZE); if (!cfg_base) { dev_err(&pdev->dev, "failed to map PCI resource #0\n"); + err = -ENOMEM; goto failure_release_regions; } reg_base = pci_iomap(pdev, 1, PEAK_PCI_CHAN_SIZE * channels); if (!reg_base) { dev_err(&pdev->dev, "failed to map PCI resource #1\n"); + err = -ENOMEM; goto failure_unmap_cfg_base; } -- cgit v0.10.2 From ba9b6f9f7a9eccf09440848d1c63e9f4c77eaa58 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 3 Oct 2012 18:17:53 +0200 Subject: can: peak_pcmcia: fix error return code Convert a nonnegative error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // ( if@p1 (\(ret < 0\|ret != 0\)) { ... return ret; } | ret@p1 = 0 ) ... when != ret = e1 when != &ret *if(...) { ... when != ret = e2 when forall return ret; } // Signed-off-by: Peter Senna Tschudin Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/sja1000/peak_pcmcia.c b/drivers/net/can/sja1000/peak_pcmcia.c index ec6bd9d..272a85f 100644 --- a/drivers/net/can/sja1000/peak_pcmcia.c +++ b/drivers/net/can/sja1000/peak_pcmcia.c @@ -686,8 +686,10 @@ static int __devinit pcan_probe(struct pcmcia_device *pdev) /* detect available channels */ pcan_add_channels(card); - if (!card->chan_count) + if (!card->chan_count) { + err = -ENOMEM; goto probe_err_4; + } /* init the timer which controls the leds */ init_timer(&card->led_timer); -- cgit v0.10.2 From 8cf437a0dc2acacb4efa5eb73af9067bba3d2232 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 4 Oct 2012 16:22:13 +0200 Subject: can: mpc5xxx_can: fix section type conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit: 6d99c4c can: mpc5xxx_can: make data used as *of_device_id.data const both "struct mpc5xxx_can_data mpc5200_can_data" and "mpc5121_can_data" are marked as "const" but also as "__devinitdata". This leads to the following compile error: drivers/net/can/mscan/mpc5xxx_can.c:383: error: mpc5200_can_data causes a section type conflict drivers/net/can/mscan/mpc5xxx_can.c:383: error: mpc5200_can_data causes a section type conflict drivers/net/can/mscan/mpc5xxx_can.c:388: error: mpc5121_can_data causes a section type conflict drivers/net/can/mscan/mpc5xxx_can.c:388: error: mpc5121_can_data causes a section type conflict This patch changes the "__devinitdata" to "__devinitconst" and marks the "struct of_device_id mpc5xxx_can_table" as "const" and "__devinitconst", too. Acked-by: Uwe Kleine-König Acked-by: Arnd Bergmann Signed-off-by: Marc Kleine-Budde diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index c975999..799c354 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -247,7 +247,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, } #endif /* CONFIG_PPC_MPC512x */ -static struct of_device_id mpc5xxx_can_table[]; +static const struct of_device_id mpc5xxx_can_table[]; static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev) { const struct of_device_id *match; @@ -380,17 +380,17 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev) } #endif -static const struct mpc5xxx_can_data __devinitdata mpc5200_can_data = { +static const struct mpc5xxx_can_data __devinitconst mpc5200_can_data = { .type = MSCAN_TYPE_MPC5200, .get_clock = mpc52xx_can_get_clock, }; -static const struct mpc5xxx_can_data __devinitdata mpc5121_can_data = { +static const struct mpc5xxx_can_data __devinitconst mpc5121_can_data = { .type = MSCAN_TYPE_MPC5121, .get_clock = mpc512x_can_get_clock, }; -static struct of_device_id __devinitdata mpc5xxx_can_table[] = { +static const struct of_device_id __devinitconst mpc5xxx_can_table[] = { { .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, }, /* Note that only MPC5121 Rev. 2 (and later) is supported */ { .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, }, -- cgit v0.10.2 From f4ef85bbda96324785097356336bc79cdd37db0a Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 4 Oct 2012 01:25:26 +0000 Subject: ipv4: add a fib_type to fib_info commit d2d68ba9fe8 (ipv4: Cache input routes in fib_info nexthops.) introduced a regression for forwarding. This was hard to reproduce but the symptom was that packets were delivered to local host instead of being forwarded. David suggested to add fib_type to fib_info so that we dont inadvertently share same fib_info for different purposes. With help from Julian Anastasov who provided very helpful hints, reproduced here : Can it be a problem related to fib_info reuse from different routes. For example, when local IP address is created for subnet we have: broadcast 192.168.0.255 dev DEV proto kernel scope link src 192.168.0.1 192.168.0.0/24 dev DEV proto kernel scope link src 192.168.0.1 local 192.168.0.1 dev DEV proto kernel scope host src 192.168.0.1 The "dev DEV proto kernel scope link src 192.168.0.1" is a reused fib_info structure where we put cached routes. The result can be same fib_info for 192.168.0.255 and 192.168.0.0/24. RTN_BROADCAST is cached only for input routes. Incoming broadcast to 192.168.0.255 can be cached and can cause problems for traffic forwarded to 192.168.0.0/24. So, this patch should solve the problem because it separates the broadcast from unicast traffic. And the ip_route_input_slow caching will work for local and broadcast input routes (above routes 1 and 3) just because they differ in scope and use different fib_info. Many thanks to Chris Clayton for his patience and help. Reported-by: Chris Clayton Bisected-by: Chris Clayton Reported-by: Dave Jones Signed-off-by: Eric Dumazet Cc: Julian Anastasov Tested-by: Chris Clayton Signed-off-by: David S. Miller diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 926142e..9497be1 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -102,6 +102,7 @@ struct fib_info { unsigned char fib_dead; unsigned char fib_protocol; unsigned char fib_scope; + unsigned char fib_type; __be32 fib_prefsrc; u32 fib_priority; u32 *fib_metrics; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 3509065..2677530 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -314,6 +314,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi) nfi->fib_scope == fi->fib_scope && nfi->fib_prefsrc == fi->fib_prefsrc && nfi->fib_priority == fi->fib_priority && + nfi->fib_type == fi->fib_type && memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(u32) * RTAX_MAX) == 0 && ((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_F_DEAD) == 0 && @@ -833,6 +834,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg) fi->fib_flags = cfg->fc_flags; fi->fib_priority = cfg->fc_priority; fi->fib_prefsrc = cfg->fc_prefsrc; + fi->fib_type = cfg->fc_type; fi->fib_nhs = nhs; change_nexthops(fi) { -- cgit v0.10.2 From 575659936f9d392b93b03ce97a58dbd4fce18abd Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 3 Oct 2012 05:43:21 +0000 Subject: sctp: fix a typo in prototype of __sctp_rcv_lookup() Just to avoid confusion when people only reads this prototype. Signed-off-by: Nicolas Dichtel Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/net/sctp/input.c b/net/sctp/input.c index 25dfe73..8bd3c27 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -68,8 +68,8 @@ static int sctp_rcv_ootb(struct sk_buff *); static struct sctp_association *__sctp_rcv_lookup(struct net *net, struct sk_buff *skb, - const union sctp_addr *laddr, const union sctp_addr *paddr, + const union sctp_addr *laddr, struct sctp_transport **transportp); static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net, const union sctp_addr *laddr); -- cgit v0.10.2 From edfee0339e681a784ebacec7e8c2dc97dc6d2839 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 3 Oct 2012 05:43:22 +0000 Subject: sctp: check src addr when processing SACK to update transport state Suppose we have an SCTP connection with two paths. After connection is established, path1 is not available, thus this path is marked as inactive. Then traffic goes through path2, but for some reasons packets are delayed (after rto.max). Because packets are delayed, the retransmit mechanism will switch again to path1. At this time, we receive a delayed SACK from path2. When we update the state of the path in sctp_check_transmitted(), we do not take into account the source address of the SACK, hence we update the wrong path. Signed-off-by: Nicolas Dichtel Acked-by: Vlad Yasevich Signed-off-by: David S. Miller diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 0fef00f..64158aa 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1068,7 +1068,7 @@ void sctp_outq_init(struct sctp_association *, struct sctp_outq *); void sctp_outq_teardown(struct sctp_outq *); void sctp_outq_free(struct sctp_outq*); int sctp_outq_tail(struct sctp_outq *, struct sctp_chunk *chunk); -int sctp_outq_sack(struct sctp_outq *, struct sctp_sackhdr *); +int sctp_outq_sack(struct sctp_outq *, struct sctp_chunk *); int sctp_outq_is_empty(const struct sctp_outq *); void sctp_outq_restart(struct sctp_outq *); diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index d16632e..1b4a7f8 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -63,6 +63,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn); static void sctp_check_transmitted(struct sctp_outq *q, struct list_head *transmitted_queue, struct sctp_transport *transport, + union sctp_addr *saddr, struct sctp_sackhdr *sack, __u32 *highest_new_tsn); @@ -1139,9 +1140,10 @@ static void sctp_sack_update_unack_data(struct sctp_association *assoc, * Process the SACK against the outqueue. Mostly, this just frees * things off the transmitted queue. */ -int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) +int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk) { struct sctp_association *asoc = q->asoc; + struct sctp_sackhdr *sack = chunk->subh.sack_hdr; struct sctp_transport *transport; struct sctp_chunk *tchunk = NULL; struct list_head *lchunk, *transport_list, *temp; @@ -1210,7 +1212,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) /* Run through the retransmit queue. Credit bytes received * and free those chunks that we can. */ - sctp_check_transmitted(q, &q->retransmit, NULL, sack, &highest_new_tsn); + sctp_check_transmitted(q, &q->retransmit, NULL, NULL, sack, &highest_new_tsn); /* Run through the transmitted queue. * Credit bytes received and free those chunks which we can. @@ -1219,7 +1221,8 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_sackhdr *sack) */ list_for_each_entry(transport, transport_list, transports) { sctp_check_transmitted(q, &transport->transmitted, - transport, sack, &highest_new_tsn); + transport, &chunk->source, sack, + &highest_new_tsn); /* * SFR-CACC algorithm: * C) Let count_of_newacks be the number of @@ -1326,6 +1329,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q) static void sctp_check_transmitted(struct sctp_outq *q, struct list_head *transmitted_queue, struct sctp_transport *transport, + union sctp_addr *saddr, struct sctp_sackhdr *sack, __u32 *highest_new_tsn_in_sack) { @@ -1633,8 +1637,9 @@ static void sctp_check_transmitted(struct sctp_outq *q, /* Mark the destination transport address as * active if it is not so marked. */ - if ((transport->state == SCTP_INACTIVE) || - (transport->state == SCTP_UNCONFIRMED)) { + if ((transport->state == SCTP_INACTIVE || + transport->state == SCTP_UNCONFIRMED) && + sctp_cmp_addr_exact(&transport->ipaddr, saddr)) { sctp_assoc_control_transport( transport->asoc, transport, diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bcfebb9..57f7de8 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -752,11 +752,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, /* Helper function to process the process SACK command. */ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, struct sctp_association *asoc, - struct sctp_sackhdr *sackh) + struct sctp_chunk *chunk) { int err = 0; - if (sctp_outq_sack(&asoc->outqueue, sackh)) { + if (sctp_outq_sack(&asoc->outqueue, chunk)) { struct net *net = sock_net(asoc->base.sk); /* There are no more TSNs awaiting SACK. */ diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 094813b..b6adef8 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -3179,7 +3179,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net, return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); /* Return this SACK for further processing. */ - sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); + sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_CHUNK(chunk)); /* Note: We do the rest of the work on the PROCESS_SACK * sideeffect. -- cgit v0.10.2 From 49ee49202b4ac4be95d05e4bf24a9ac8b54c5528 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 3 Oct 2012 23:05:26 +0000 Subject: bonding: set qdisc_tx_busylock to avoid LOCKDEP splat If a qdisc is installed on a bonding device, its possible to get following lockdep splat under stress : ============================================= [ INFO: possible recursive locking detected ] 3.6.0+ #211 Not tainted --------------------------------------------- ping/4876 is trying to acquire lock: (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock){+.-...}, at: [] dev_queue_xmit+0xe1/0x830 but task is already holding lock: (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock){+.-...}, at: [] dev_queue_xmit+0xe1/0x830 other info that might help us debug this: Possible unsafe locking scenario: CPU0 ---- lock(dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); lock(dev->qdisc_tx_busylock ?: &qdisc_tx_busylock); *** DEADLOCK *** May be due to missing lock nesting notation 6 locks held by ping/4876: #0: (sk_lock-AF_INET){+.+.+.}, at: [] raw_sendmsg+0x600/0xc30 #1: (rcu_read_lock_bh){.+....}, at: [] ip_finish_output+0x12d/0x870 #2: (rcu_read_lock_bh){.+....}, at: [] dev_queue_xmit+0x0/0x830 #3: (dev->qdisc_tx_busylock ?: &qdisc_tx_busylock){+.-...}, at: [] dev_queue_xmit+0xe1/0x830 #4: (&bond->lock){++.?..}, at: [] bond_start_xmit+0x31/0x4b0 [bonding] #5: (rcu_read_lock_bh){.+....}, at: [] dev_queue_xmit+0x0/0x830 stack backtrace: Pid: 4876, comm: ping Not tainted 3.6.0+ #211 Call Trace: [] __lock_acquire+0x715/0x1b80 [] ? mark_held_locks+0x9b/0x100 [] lock_acquire+0x92/0x1d0 [] ? dev_queue_xmit+0xe1/0x830 [] _raw_spin_lock+0x3c/0x50 [] ? dev_queue_xmit+0xe1/0x830 [] ? rcu_read_lock_bh_held+0x5d/0x90 [] dev_queue_xmit+0xe1/0x830 [] ? netdev_pick_tx+0x570/0x570 [] bond_start_xmit+0x1da/0x4b0 [bonding] [] dev_hard_start_xmit+0x240/0x6b0 [] sch_direct_xmit+0xfe/0x2a0 [] dev_queue_xmit+0x199/0x830 [] ? netdev_pick_tx+0x570/0x570 [] ip_finish_output+0x5df/0x870 [] ? ip_finish_output+0x12d/0x870 [] ip_output+0x54/0xf0 [] ip_local_out+0x28/0x90 [] ip_send_skb+0x14/0x50 [] ip_push_pending_frames+0x32/0x40 [] raw_sendmsg+0x93a/0xc30 [] ? selinux_file_send_sigiotask+0x1f0/0x1f0 [] ? __lock_is_held+0x54/0x80 [] ? inet_recvmsg+0x220/0x220 [] ? __lock_is_held+0x54/0x80 [] inet_sendmsg+0x125/0x240 [] ? inet_recvmsg+0x220/0x220 [] sock_sendmsg+0xab/0xe0 [] ? lock_release_non_nested+0xa0/0x2e0 [] ? lock_release_non_nested+0xa0/0x2e0 [] __sys_sendmsg+0x37c/0x390 [] ? fsnotify+0x2ca/0x7e0 [] ? fsnotify+0x88/0x7e0 [] ? put_ldisc+0x56/0xd0 [] ? fget_light+0x3da/0x510 [] sys_sendmsg+0x44/0x80 [] system_call_fastpath+0x16/0x1b Avoid this problem using a distinct lock_class_key for bonding devices. Signed-off-by: Eric Dumazet Cc: Jay Vosburgh Cc: Andy Gospodarek Signed-off-by: David S. Miller diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7858c58..b721902 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4826,6 +4826,7 @@ static int bond_check_params(struct bond_params *params) static struct lock_class_key bonding_netdev_xmit_lock_key; static struct lock_class_key bonding_netdev_addr_lock_key; +static struct lock_class_key bonding_tx_busylock_key; static void bond_set_lockdep_class_one(struct net_device *dev, struct netdev_queue *txq, @@ -4840,6 +4841,7 @@ static void bond_set_lockdep_class(struct net_device *dev) lockdep_set_class(&dev->addr_list_lock, &bonding_netdev_addr_lock_key); netdev_for_each_tx_queue(dev, bond_set_lockdep_class_one, NULL); + dev->qdisc_tx_busylock = &bonding_tx_busylock_key; } /* -- cgit v0.10.2 From b3c581d5d7130fc7f2eab9ab14c8de8882b42380 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 3 Oct 2012 23:18:39 +0000 Subject: team: set qdisc_tx_busylock to avoid LOCKDEP splat If a qdisc is installed on a team device, its possible to get a lockdep splat under stress, because nested dev_queue_xmit() can lock busylock a second time (on a different device, so its a false positive) Avoid this problem using a distinct lock_class_key for team devices. Signed-off-by: Eric Dumazet Cc: Jiri Pirko Acked-by: Jiri Pirko Signed-off-by: David S. Miller diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 5c7547c..d44cca3 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1315,6 +1315,7 @@ static const struct team_option team_options[] = { static struct lock_class_key team_netdev_xmit_lock_key; static struct lock_class_key team_netdev_addr_lock_key; +static struct lock_class_key team_tx_busylock_key; static void team_set_lockdep_class_one(struct net_device *dev, struct netdev_queue *txq, @@ -1327,6 +1328,7 @@ static void team_set_lockdep_class(struct net_device *dev) { lockdep_set_class(&dev->addr_list_lock, &team_netdev_addr_lock_key); netdev_for_each_tx_queue(dev, team_set_lockdep_class_one, NULL); + dev->qdisc_tx_busylock = &team_tx_busylock_key; } static int team_init(struct net_device *dev) -- cgit v0.10.2 From 096895818cbf3382dc318f369e642fb7460ccb26 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Oct 2012 03:36:13 +0000 Subject: silence some noisy printks in irda Fuzzing causes these printks to spew constantly. Changing them to DEBUG statements is consistent with other usage in the file, and makes them disappear when CONFIG_IRDA_DEBUG is disabled. Signed-off-by: Dave Jones Signed-off-by: David S. Miller diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index bb738c9..b833677 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -468,7 +468,7 @@ static int irda_open_tsap(struct irda_sock *self, __u8 tsap_sel, char *name) notify_t notify; if (self->tsap) { - IRDA_WARNING("%s: busy!\n", __func__); + IRDA_DEBUG(0, "%s: busy!\n", __func__); return -EBUSY; } diff --git a/net/irda/irttp.c b/net/irda/irttp.c index 5c93f29..1002e33 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c @@ -440,7 +440,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify) */ lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0); if (lsap == NULL) { - IRDA_WARNING("%s: unable to allocate LSAP!!\n", __func__); + IRDA_DEBUG(0, "%s: unable to allocate LSAP!!\n", __func__); return NULL; } -- cgit v0.10.2 From e57edf6b6dba975eceede20b4b13699d4e88cd78 Mon Sep 17 00:00:00 2001 From: Erik Hugne Date: Thu, 4 Oct 2012 05:00:43 +0000 Subject: tipc: prevent dropped connections due to rcvbuf overflow When large buffers are sent over connected TIPC sockets, it is likely that the sk_backlog will be filled up on the receiver side, but the TIPC flow control mechanism is happily unaware of this since that is based on message count. The sender will receive a TIPC_ERR_OVERLOAD message when this occurs and drop it's side of the connection, leaving it stale on the receiver end. By increasing the sk_rcvbuf to a 'worst case' value, we avoid the overload caused by a full backlog queue and the flow control will work properly. This worst case value is the max TIPC message size times the flow control window, multiplied by two because a sender will transmit up to double the window size before a port is marked congested. We multiply this by 2 to account for the sk_buff and other overheads. Signed-off-by: Erik Hugne Signed-off-by: David S. Miller diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 09dc5b9..fd5f042 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -220,6 +220,7 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol, sock_init_data(sock, sk); sk->sk_backlog_rcv = backlog_rcv; + sk->sk_rcvbuf = TIPC_FLOW_CONTROL_WIN * 2 * TIPC_MAX_USER_MSG_SIZE * 2; tipc_sk(sk)->p = tp_ptr; tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT; -- cgit v0.10.2 From 32418cfe495c95013be2e805c087db89dcefac6d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 4 Oct 2012 09:51:11 +0000 Subject: Remove noisy printks from llcp_sock_connect Validation of userspace input shouldn't trigger dmesg spamming. Signed-off-by: Dave Jones Signed-off-by: David S. Miller diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 40f056d..63e4cdc 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -497,15 +497,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags); if (!addr || len < sizeof(struct sockaddr_nfc) || - addr->sa_family != AF_NFC) { - pr_err("Invalid socket\n"); + addr->sa_family != AF_NFC) return -EINVAL; - } - if (addr->service_name_len == 0 && addr->dsap == 0) { - pr_err("Missing service name or dsap\n"); + if (addr->service_name_len == 0 && addr->dsap == 0) return -EINVAL; - } pr_debug("addr dev_idx=%u target_idx=%u protocol=%u\n", addr->dev_idx, addr->target_idx, addr->nfc_protocol); -- cgit v0.10.2 From 6825a26c2dc21eb4f8df9c06d3786ddec97cf53b Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 19 Sep 2012 19:25:34 +0000 Subject: ipv6: release reference of ip6_null_entry's dst entry in __ip6_del_rt as we hold dst_entry before we call __ip6_del_rt, so we should alse call dst_release not only return -ENOENT when the rt6_info is ip6_null_entry. and we already hold the dst entry, so I think it's safe to call dst_release out of the write-read lock. Signed-off-by: Gao feng Signed-off-by: David S. Miller diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d1ddbc6..7c7e963 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1593,17 +1593,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) struct fib6_table *table; struct net *net = dev_net(rt->dst.dev); - if (rt == net->ipv6.ip6_null_entry) - return -ENOENT; + if (rt == net->ipv6.ip6_null_entry) { + err = -ENOENT; + goto out; + } table = rt->rt6i_table; write_lock_bh(&table->tb6_lock); - err = fib6_del(rt, info); - dst_release(&rt->dst); - write_unlock_bh(&table->tb6_lock); +out: + dst_release(&rt->dst); return err; } -- cgit v0.10.2