]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
authorDavid S. Miller <davem@davemloft.net>
Fri, 19 Nov 2010 21:13:47 +0000 (13:13 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 19 Nov 2010 21:13:47 +0000 (13:13 -0800)
Conflicts:
drivers/net/bonding/bond_main.c
net/core/net-sysfs.c
net/ipv6/addrconf.c

1  2 
drivers/net/bnx2x/bnx2x_main.c
drivers/net/bonding/bond_main.c
drivers/net/wireless/ath/ath9k/eeprom_9287.c
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/carl9170/usb.c
include/net/cfg80211.h
include/net/neighbour.h
net/core/filter.c
net/ipv4/icmp.c
net/ipv6/addrconf.c

index 7ffcb086cb6fb01270b909cca4e8c35170470afe,9709b8569666d56ff84fb263429eb6f27c244033..92057d7058daf8db70956f3999d0d1075ecb9740
@@@ -8078,7 -8078,7 +8078,7 @@@ static void __devinit bnx2x_get_port_hw
        int port = BP_PORT(bp);
        u32 val, val2;
        u32 config;
 -      u32 ext_phy_type, ext_phy_config;;
 +      u32 ext_phy_type, ext_phy_config;
  
        bp->link_params.bp = bp;
        bp->link_params.port = port;
@@@ -9064,7 -9064,7 +9064,7 @@@ static int __devinit bnx2x_init_one(str
        default:
                pr_err("Unknown board_type (%ld), aborting\n",
                           ent->driver_data);
-               return ENODEV;
+               return -ENODEV;
        }
  
        cid_count += CNIC_CONTEXT_USE;
index e588b2e1c3b34c3979b77bd2fa0ce18ebea053ad,71a169740d05daf463b04f2ff591a943f8c1847e..0273ad0b57bb00167591414ca2937ce84e6794b1
@@@ -873,11 -873,17 +873,11 @@@ static void bond_mc_del(struct bonding 
  static void __bond_resend_igmp_join_requests(struct net_device *dev)
  {
        struct in_device *in_dev;
 -      struct ip_mc_list *im;
  
        rcu_read_lock();
        in_dev = __in_dev_get_rcu(dev);
 -      if (in_dev) {
 -              read_lock(&in_dev->mc_list_lock);
 -              for (im = in_dev->mc_list; im; im = im->next)
 -                      ip_mc_rejoin_group(im);
 -              read_unlock(&in_dev->mc_list_lock);
 -      }
 -
 +      if (in_dev)
-                       ip_mc_rejoin_groups(in_dev);
++              ip_mc_rejoin_groups(in_dev);
        rcu_read_unlock();
  }
  
@@@ -3205,7 -3211,7 +3205,7 @@@ out
  #ifdef CONFIG_PROC_FS
  
  static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
 -      __acquires(&dev_base_lock)
 +      __acquires(RCU)
        __acquires(&bond->lock)
  {
        struct bonding *bond = seq->private;
        int i;
  
        /* make sure the bond won't be taken away */
 -      read_lock(&dev_base_lock);
 +      rcu_read_lock();
        read_lock(&bond->lock);
  
        if (*pos == 0)
@@@ -3244,12 -3250,12 +3244,12 @@@ static void *bond_info_seq_next(struct 
  
  static void bond_info_seq_stop(struct seq_file *seq, void *v)
        __releases(&bond->lock)
 -      __releases(&dev_base_lock)
 +      __releases(RCU)
  {
        struct bonding *bond = seq->private;
  
        read_unlock(&bond->lock);
 -      read_unlock(&dev_base_lock);
 +      rcu_read_unlock();
  }
  
  static void bond_info_show_master(struct seq_file *seq)
index ebf7a89f547cafacfa64ae3c227e94716422f7a2,195406db3bd899b28f96c7b8214428822c3735db..3ad1de253c8a4277675b9bede13a9103edbf6957
@@@ -37,7 -37,7 +37,7 @@@ static bool ath9k_hw_ar9287_fill_eeprom
        int addr, eep_start_loc;
        eep_data = (u16 *)eep;
  
-       if (ah->hw_version.devid == 0x7015)
+       if (AR9287_HTC_DEVID(ah))
                eep_start_loc = AR9287_HTC_EEP_START_LOC;
        else
                eep_start_loc = AR9287_EEP_START_LOC;
@@@ -853,7 -853,7 +853,7 @@@ static void ath9k_hw_ar9287_set_txpower
                                        struct ath9k_channel *chan, u16 cfgCtl,
                                        u8 twiceAntennaReduction,
                                        u8 twiceMaxRegulatoryPower,
 -                                      u8 powerLimit)
 +                                      u8 powerLimit, bool test)
  {
        struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
        struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
  
        ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
  
 +      regulatory->max_power_level = 0;
        for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
                ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
                if (ratesArray[i] > AR9287_MAX_RATE_POWER)
                        ratesArray[i] = AR9287_MAX_RATE_POWER;
 +
 +              if (ratesArray[i] > regulatory->max_power_level)
 +                      regulatory->max_power_level = ratesArray[i];
        }
  
 +      if (test)
 +              return;
 +
 +      if (IS_CHAN_2GHZ(chan))
 +              i = rate1l;
 +      else
 +              i = rate6mb;
 +
 +      regulatory->max_power_level = ratesArray[i];
 +
        if (AR_SREV_9280_20_OR_LATER(ah)) {
                for (i = 0; i < Ar5416RateSize; i++)
                        ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
                          | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
                          | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
        }
 -
 -      if (IS_CHAN_2GHZ(chan))
 -              i = rate1l;
 -      else
 -              i = rate6mb;
 -
 -      if (AR_SREV_9280_20_OR_LATER(ah))
 -              regulatory->max_power_level =
 -                      ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
 -      else
 -              regulatory->max_power_level = ratesArray[i];
  }
  
  static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
index 5324ffd96ec76e18cbd951a1581cbacf041896d8,29d80ca783933684b7c5c531cbb970ee7e006cda..77958675b55f6eeaf56ad2e59810f7bf667359c6
  /* TX */
  /******/
  
 +static const int subtype_txq_to_hwq[] = {
 +      [WME_AC_BE] = ATH_TXQ_AC_BE,
 +      [WME_AC_BK] = ATH_TXQ_AC_BK,
 +      [WME_AC_VI] = ATH_TXQ_AC_VI,
 +      [WME_AC_VO] = ATH_TXQ_AC_VO,
 +};
 +
  #define ATH9K_HTC_INIT_TXQ(subtype) do {                      \
 -              qi.tqi_subtype = subtype;                       \
 +              qi.tqi_subtype = subtype_txq_to_hwq[subtype];   \
                qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;             \
                qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;            \
                qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;            \
@@@ -128,7 -121,7 +128,7 @@@ int ath9k_htc_tx_start(struct ath9k_htc
                        tx_hdr.data_type = ATH9K_HTC_NORMAL;
                }
  
-               if (ieee80211_is_data(fc)) {
+               if (ieee80211_is_data_qos(fc)) {
                        qc = ieee80211_get_qos_ctl(hdr);
                        tx_hdr.tidno = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
                }
index d28e580bb4863d4483435b6600a9ac0fd15098a5,92bc5c5f48768ac42ca4b1bd02690d9d38ebed80..5c26818d79ecb257b4827885b87cd01fb21bd866
@@@ -398,8 -398,7 +398,8 @@@ static void ath9k_init_crypto(struct at
  
  static int ath9k_init_btcoex(struct ath_softc *sc)
  {
 -      int r, qnum;
 +      struct ath_txq *txq;
 +      int r;
  
        switch (sc->sc_ah->btcoex_hw.scheme) {
        case ATH_BTCOEX_CFG_NONE:
                r = ath_init_btcoex_timer(sc);
                if (r)
                        return -1;
 -              qnum = sc->tx.hwq_map[WME_AC_BE];
 -              ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
 +              txq = sc->tx.txq_map[WME_AC_BE];
 +              ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
                sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
                break;
        default:
  
  static int ath9k_init_queues(struct ath_softc *sc)
  {
 -      struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int i = 0;
  
 -      for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
 -              sc->tx.hwq_map[i] = -1;
 -
        sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
 -      if (sc->beacon.beaconq == -1) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup a beacon xmit queue\n");
 -              goto err;
 -      }
 -
        sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
 -      if (sc->beacon.cabq == NULL) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup CAB xmit queue\n");
 -              goto err;
 -      }
  
        sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
        ath_cabq_update(sc);
  
 -      if (!ath_tx_setup(sc, WME_AC_BK)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for BK traffic\n");
 -              goto err;
 -      }
 -
 -      if (!ath_tx_setup(sc, WME_AC_BE)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for BE traffic\n");
 -              goto err;
 -      }
 -      if (!ath_tx_setup(sc, WME_AC_VI)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for VI traffic\n");
 -              goto err;
 -      }
 -      if (!ath_tx_setup(sc, WME_AC_VO)) {
 -              ath_print(common, ATH_DBG_FATAL,
 -                        "Unable to setup xmit queue for VO traffic\n");
 -              goto err;
 -      }
 +      for (i = 0; i < WME_NUM_AC; i++)
 +              sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
  
        return 0;
 -
 -err:
 -      for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
 -              if (ATH_TXQ_SETUP(sc, i))
 -                      ath_tx_cleanupq(sc, &sc->tx.txq[i]);
 -
 -      return -EIO;
  }
  
  static int ath9k_init_channels_rates(struct ath_softc *sc)
@@@ -543,6 -583,7 +543,6 @@@ static int ath9k_init_softc(u16 devid, 
        spin_lock_init(&common->cc_lock);
  
        spin_lock_init(&sc->wiphy_lock);
 -      spin_lock_init(&sc->sc_resetlock);
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
@@@ -604,37 -645,6 +604,37 @@@ err_hw
        return ret;
  }
  
 +static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
 +{
 +      struct ieee80211_supported_band *sband;
 +      struct ieee80211_channel *chan;
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
 +      int i;
 +
 +      sband = &sc->sbands[band];
 +      for (i = 0; i < sband->n_channels; i++) {
 +              chan = &sband->channels[i];
 +              ah->curchan = &ah->channels[chan->hw_value];
 +              ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
 +              ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
 +              chan->max_power = reg->max_power_level / 2;
 +      }
 +}
 +
 +static void ath9k_init_txpower_limits(struct ath_softc *sc)
 +{
 +      struct ath_hw *ah = sc->sc_ah;
 +      struct ath9k_channel *curchan = ah->curchan;
 +
 +      if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
 +              ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
 +      if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
 +              ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
 +
 +      ah->curchan = curchan;
 +}
 +
  void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
  {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@@ -696,7 -706,6 +696,7 @@@ int ath9k_init_device(u16 devid, struc
                    const struct ath_bus_ops *bus_ops)
  {
        struct ieee80211_hw *hw = sc->hw;
 +      struct ath_wiphy *aphy = hw->priv;
        struct ath_common *common;
        struct ath_hw *ah;
        int error = 0;
        if (error != 0)
                goto error_rx;
  
 +      ath9k_init_txpower_limits(sc);
 +
        /* Register with mac80211 */
        error = ieee80211_register_hw(hw);
        if (error)
        INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
        INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
        sc->wiphy_scheduler_int = msecs_to_jiffies(500);
 +      aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
  
        ath_init_leds(sc);
        ath_start_rfkill_poll(sc);
@@@ -811,8 -817,6 +811,6 @@@ void ath9k_deinit_device(struct ath_sof
  
        ath9k_ps_wakeup(sc);
  
-       pm_qos_remove_request(&ath9k_pm_qos_req);
        wiphy_rfkill_stop_polling(sc->hw->wiphy);
        ath_deinit_leds(sc);
  
        }
  
        ieee80211_unregister_hw(hw);
+       pm_qos_remove_request(&ath9k_pm_qos_req);
        ath_rx_cleanup(sc);
        ath_tx_cleanup(sc);
        ath9k_deinit_softc(sc);
index 82c5f1c5065096f3807392d3ab07fa64321ad4a8,7504ed14c72575a7befb91b0c0d9dd2684660af9..a268053e18e5e1e2f430deb19d2edc1ab158fd1d
@@@ -433,7 -433,7 +433,7 @@@ static void carl9170_usb_rx_complete(st
                         * device.
                         */
  
 -                      carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
 +                      ieee80211_queue_work(ar->hw, &ar->ping_work);
                }
        } else {
                /*
@@@ -553,12 -553,12 +553,12 @@@ static int carl9170_usb_flush(struct ar
                usb_free_urb(urb);
        }
  
-       ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, HZ);
+       ret = usb_wait_anchor_empty_timeout(&ar->tx_cmd, 1000);
        if (ret == 0)
                err = -ETIMEDOUT;
  
        /* lets wait a while until the tx - queues are dried out */
-       ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, HZ);
+       ret = usb_wait_anchor_empty_timeout(&ar->tx_anch, 1000);
        if (ret == 0)
                err = -ETIMEDOUT;
  
diff --combined include/net/cfg80211.h
index e5702f5ac57c83052fcef2381227b1c2f72204b1,97b8b7c9b63cf9854e3b8c2e83154c8ecb0bea06..772dea243e5dfd15affc97520e4735a931ce1af3
@@@ -1321,14 -1321,13 +1321,14 @@@ struct cfg80211_ops 
   *    initiator is %REGDOM_SET_BY_CORE).
   * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will
   *    ignore regulatory domain settings until it gets its own regulatory
 - *    domain via its regulatory_hint(). After its gets its own regulatory
 - *    domain it will only allow further regulatory domain settings to
 - *    further enhance compliance. For example if channel 13 and 14 are
 - *    disabled by this regulatory domain no user regulatory domain can
 - *    enable these channels at a later time. This can be used for devices
 - *    which do not have calibration information gauranteed for frequencies
 - *    or settings outside of its regulatory domain.
 + *    domain via its regulatory_hint() unless the regulatory hint is
 + *    from a country IE. After its gets its own regulatory domain it will
 + *    only allow further regulatory domain settings to further enhance
 + *    compliance. For example if channel 13 and 14 are disabled by this
 + *    regulatory domain no user regulatory domain can enable these channels
 + *    at a later time. This can be used for devices which do not have
 + *    calibration information guaranteed for frequencies or settings
 + *    outside of its regulatory domain.
   * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
   *    that passive scan flags and beaconing flags may not be lifted by
   *    cfg80211 due to regulatory beacon hints. For more information on beacon
@@@ -1356,7 -1355,7 +1356,7 @@@ enum wiphy_flags 
        WIPHY_FLAG_4ADDR_AP                     = BIT(5),
        WIPHY_FLAG_4ADDR_STATION                = BIT(6),
        WIPHY_FLAG_CONTROL_PORT_PROTOCOL        = BIT(7),
-       WIPHY_FLAG_IBSS_RSN                     = BIT(7),
+       WIPHY_FLAG_IBSS_RSN                     = BIT(8),
  };
  
  struct mac_address {
diff --combined include/net/neighbour.h
index 815b2ce9f4a496768fff673321a79bd39c0545c9,6beb1ffc2b7fcfe9d360717ccde3f70bd8ac0e3d..4014b623880cf529e3bb5b184a5b31dee650a8b5
@@@ -96,16 -96,16 +96,16 @@@ struct neighbour 
        struct neigh_parms      *parms;
        unsigned long           confirmed;
        unsigned long           updated;
 -      __u8                    flags;
 -      __u8                    nud_state;
 -      __u8                    type;
 -      __u8                    dead;
 +      rwlock_t                lock;
        atomic_t                refcnt;
        struct sk_buff_head     arp_queue;
        struct timer_list       timer;
        unsigned long           used;
        atomic_t                probes;
 -      rwlock_t                lock;
 +      __u8                    flags;
 +      __u8                    nud_state;
 +      __u8                    type;
 +      __u8                    dead;
        seqlock_t               ha_lock;
        unsigned char           ha[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
        struct hh_cache         *hh;
@@@ -303,7 -303,7 +303,7 @@@ static inline void neigh_confirm(struc
  
  static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
  {
-       unsigned long now = ACCESS_ONCE(jiffies);
+       unsigned long now = jiffies;
        
        if (neigh->used != now)
                neigh->used = now;
diff --combined net/core/filter.c
index 23e0a2a9a4dec09de358839ed6c396e74cd802fe,c1ee800bc080c3faf33033e1659021a0a356f7ce..a44d27f9f0f0aa4975d95b8e8c56bebb3f0fda6b
  #include <asm/uaccess.h>
  #include <asm/unaligned.h>
  #include <linux/filter.h>
 +#include <linux/reciprocal_div.h>
 +
 +enum {
 +      BPF_S_RET_K = 1,
 +      BPF_S_RET_A,
 +      BPF_S_ALU_ADD_K,
 +      BPF_S_ALU_ADD_X,
 +      BPF_S_ALU_SUB_K,
 +      BPF_S_ALU_SUB_X,
 +      BPF_S_ALU_MUL_K,
 +      BPF_S_ALU_MUL_X,
 +      BPF_S_ALU_DIV_X,
 +      BPF_S_ALU_AND_K,
 +      BPF_S_ALU_AND_X,
 +      BPF_S_ALU_OR_K,
 +      BPF_S_ALU_OR_X,
 +      BPF_S_ALU_LSH_K,
 +      BPF_S_ALU_LSH_X,
 +      BPF_S_ALU_RSH_K,
 +      BPF_S_ALU_RSH_X,
 +      BPF_S_ALU_NEG,
 +      BPF_S_LD_W_ABS,
 +      BPF_S_LD_H_ABS,
 +      BPF_S_LD_B_ABS,
 +      BPF_S_LD_W_LEN,
 +      BPF_S_LD_W_IND,
 +      BPF_S_LD_H_IND,
 +      BPF_S_LD_B_IND,
 +      BPF_S_LD_IMM,
 +      BPF_S_LDX_W_LEN,
 +      BPF_S_LDX_B_MSH,
 +      BPF_S_LDX_IMM,
 +      BPF_S_MISC_TAX,
 +      BPF_S_MISC_TXA,
 +      BPF_S_ALU_DIV_K,
 +      BPF_S_LD_MEM,
 +      BPF_S_LDX_MEM,
 +      BPF_S_ST,
 +      BPF_S_STX,
 +      BPF_S_JMP_JA,
 +      BPF_S_JMP_JEQ_K,
 +      BPF_S_JMP_JEQ_X,
 +      BPF_S_JMP_JGE_K,
 +      BPF_S_JMP_JGE_X,
 +      BPF_S_JMP_JGT_K,
 +      BPF_S_JMP_JGT_X,
 +      BPF_S_JMP_JSET_K,
 +      BPF_S_JMP_JSET_X,
 +};
  
  /* No hurry in this branch */
  static void *__load_pointer(struct sk_buff *skb, int k)
@@@ -138,7 -89,7 +138,7 @@@ int sk_filter(struct sock *sk, struct s
        rcu_read_lock_bh();
        filter = rcu_dereference_bh(sk->sk_filter);
        if (filter) {
 -              unsigned int pkt_len = sk_run_filter(skb, filter->insns, filter->len);
 +              unsigned int pkt_len = sk_run_filter(skb, filter->insns);
  
                err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM;
        }
@@@ -152,15 -103,14 +152,15 @@@ EXPORT_SYMBOL(sk_filter)
   *    sk_run_filter - run a filter on a socket
   *    @skb: buffer to run the filter on
   *    @filter: filter to apply
 - *    @flen: length of filter
   *
   * Decode and apply filter instructions to the skb->data.
 - * Return length to keep, 0 for none. skb is the data we are
 - * filtering, filter is the array of filter instructions, and
 - * len is the number of filter blocks in the array.
 + * Return length to keep, 0 for none. @skb is the data we are
 + * filtering, @filter is the array of filter instructions.
 + * Because all jumps are guaranteed to be before last instruction,
 + * and last instruction guaranteed to be a RET, we dont need to check
 + * flen. (We used to pass to this function the length of filter)
   */
 -unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen)
 +unsigned int sk_run_filter(struct sk_buff *skb, const struct sock_filter *fentry)
  {
        void *ptr;
        u32 A = 0;                      /* Accumulator */
        unsigned long memvalid = 0;
        u32 tmp;
        int k;
 -      int pc;
  
        BUILD_BUG_ON(BPF_MEMWORDS > BITS_PER_LONG);
        /*
         * Process array of filter instructions.
         */
 -      for (pc = 0; pc < flen; pc++) {
 -              const struct sock_filter *fentry = &filter[pc];
 -              u32 f_k = fentry->k;
 +      for (;; fentry++) {
 +#if defined(CONFIG_X86_32)
 +#define       K (fentry->k)
 +#else
 +              const u32 K = fentry->k;
 +#endif
  
                switch (fentry->code) {
                case BPF_S_ALU_ADD_X:
                        A += X;
                        continue;
                case BPF_S_ALU_ADD_K:
 -                      A += f_k;
 +                      A += K;
                        continue;
                case BPF_S_ALU_SUB_X:
                        A -= X;
                        continue;
                case BPF_S_ALU_SUB_K:
 -                      A -= f_k;
 +                      A -= K;
                        continue;
                case BPF_S_ALU_MUL_X:
                        A *= X;
                        continue;
                case BPF_S_ALU_MUL_K:
 -                      A *= f_k;
 +                      A *= K;
                        continue;
                case BPF_S_ALU_DIV_X:
                        if (X == 0)
                        A /= X;
                        continue;
                case BPF_S_ALU_DIV_K:
 -                      A /= f_k;
 +                      A = reciprocal_divide(A, K);
                        continue;
                case BPF_S_ALU_AND_X:
                        A &= X;
                        continue;
                case BPF_S_ALU_AND_K:
 -                      A &= f_k;
 +                      A &= K;
                        continue;
                case BPF_S_ALU_OR_X:
                        A |= X;
                        continue;
                case BPF_S_ALU_OR_K:
 -                      A |= f_k;
 +                      A |= K;
                        continue;
                case BPF_S_ALU_LSH_X:
                        A <<= X;
                        continue;
                case BPF_S_ALU_LSH_K:
 -                      A <<= f_k;
 +                      A <<= K;
                        continue;
                case BPF_S_ALU_RSH_X:
                        A >>= X;
                        continue;
                case BPF_S_ALU_RSH_K:
 -                      A >>= f_k;
 +                      A >>= K;
                        continue;
                case BPF_S_ALU_NEG:
                        A = -A;
                        continue;
                case BPF_S_JMP_JA:
 -                      pc += f_k;
 +                      fentry += K;
                        continue;
                case BPF_S_JMP_JGT_K:
 -                      pc += (A > f_k) ? fentry->jt : fentry->jf;
 +                      fentry += (A > K) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JGE_K:
 -                      pc += (A >= f_k) ? fentry->jt : fentry->jf;
 +                      fentry += (A >= K) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JEQ_K:
 -                      pc += (A == f_k) ? fentry->jt : fentry->jf;
 +                      fentry += (A == K) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JSET_K:
 -                      pc += (A & f_k) ? fentry->jt : fentry->jf;
 +                      fentry += (A & K) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JGT_X:
 -                      pc += (A > X) ? fentry->jt : fentry->jf;
 +                      fentry += (A > X) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JGE_X:
 -                      pc += (A >= X) ? fentry->jt : fentry->jf;
 +                      fentry += (A >= X) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JEQ_X:
 -                      pc += (A == X) ? fentry->jt : fentry->jf;
 +                      fentry += (A == X) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_JMP_JSET_X:
 -                      pc += (A & X) ? fentry->jt : fentry->jf;
 +                      fentry += (A & X) ? fentry->jt : fentry->jf;
                        continue;
                case BPF_S_LD_W_ABS:
 -                      k = f_k;
 +                      k = K;
  load_w:
                        ptr = load_pointer(skb, k, 4, &tmp);
                        if (ptr != NULL) {
                        }
                        break;
                case BPF_S_LD_H_ABS:
 -                      k = f_k;
 +                      k = K;
  load_h:
                        ptr = load_pointer(skb, k, 2, &tmp);
                        if (ptr != NULL) {
                        }
                        break;
                case BPF_S_LD_B_ABS:
 -                      k = f_k;
 +                      k = K;
  load_b:
                        ptr = load_pointer(skb, k, 1, &tmp);
                        if (ptr != NULL) {
                        X = skb->len;
                        continue;
                case BPF_S_LD_W_IND:
 -                      k = X + f_k;
 +                      k = X + K;
                        goto load_w;
                case BPF_S_LD_H_IND:
 -                      k = X + f_k;
 +                      k = X + K;
                        goto load_h;
                case BPF_S_LD_B_IND:
 -                      k = X + f_k;
 +                      k = X + K;
                        goto load_b;
                case BPF_S_LDX_B_MSH:
 -                      ptr = load_pointer(skb, f_k, 1, &tmp);
 +                      ptr = load_pointer(skb, K, 1, &tmp);
                        if (ptr != NULL) {
                                X = (*(u8 *)ptr & 0xf) << 2;
                                continue;
                        }
                        return 0;
                case BPF_S_LD_IMM:
 -                      A = f_k;
 +                      A = K;
                        continue;
                case BPF_S_LDX_IMM:
 -                      X = f_k;
 +                      X = K;
                        continue;
                case BPF_S_LD_MEM:
 -                      A = (memvalid & (1UL << f_k)) ?
 -                              mem[f_k] : 0;
 +                      A = (memvalid & (1UL << K)) ?
 +                              mem[K] : 0;
                        continue;
                case BPF_S_LDX_MEM:
 -                      X = (memvalid & (1UL << f_k)) ?
 -                              mem[f_k] : 0;
 +                      X = (memvalid & (1UL << K)) ?
 +                              mem[K] : 0;
                        continue;
                case BPF_S_MISC_TAX:
                        X = A;
                        A = X;
                        continue;
                case BPF_S_RET_K:
 -                      return f_k;
 +                      return K;
                case BPF_S_RET_A:
                        return A;
                case BPF_S_ST:
 -                      memvalid |= 1UL << f_k;
 -                      mem[f_k] = A;
 +                      memvalid |= 1UL << K;
 +                      mem[K] = A;
                        continue;
                case BPF_S_STX:
 -                      memvalid |= 1UL << f_k;
 -                      mem[f_k] = X;
 +                      memvalid |= 1UL << K;
 +                      mem[K] = X;
                        continue;
                default:
                        WARN_ON(1);
@@@ -435,57 -383,7 +435,57 @@@ EXPORT_SYMBOL(sk_run_filter)
   */
  int sk_chk_filter(struct sock_filter *filter, int flen)
  {
 -      struct sock_filter *ftest;
 +      /*
 +       * Valid instructions are initialized to non-0.
 +       * Invalid instructions are initialized to 0.
 +       */
 +      static const u8 codes[] = {
 +              [BPF_ALU|BPF_ADD|BPF_K]  = BPF_S_ALU_ADD_K,
 +              [BPF_ALU|BPF_ADD|BPF_X]  = BPF_S_ALU_ADD_X,
 +              [BPF_ALU|BPF_SUB|BPF_K]  = BPF_S_ALU_SUB_K,
 +              [BPF_ALU|BPF_SUB|BPF_X]  = BPF_S_ALU_SUB_X,
 +              [BPF_ALU|BPF_MUL|BPF_K]  = BPF_S_ALU_MUL_K,
 +              [BPF_ALU|BPF_MUL|BPF_X]  = BPF_S_ALU_MUL_X,
 +              [BPF_ALU|BPF_DIV|BPF_X]  = BPF_S_ALU_DIV_X,
 +              [BPF_ALU|BPF_AND|BPF_K]  = BPF_S_ALU_AND_K,
 +              [BPF_ALU|BPF_AND|BPF_X]  = BPF_S_ALU_AND_X,
 +              [BPF_ALU|BPF_OR|BPF_K]   = BPF_S_ALU_OR_K,
 +              [BPF_ALU|BPF_OR|BPF_X]   = BPF_S_ALU_OR_X,
 +              [BPF_ALU|BPF_LSH|BPF_K]  = BPF_S_ALU_LSH_K,
 +              [BPF_ALU|BPF_LSH|BPF_X]  = BPF_S_ALU_LSH_X,
 +              [BPF_ALU|BPF_RSH|BPF_K]  = BPF_S_ALU_RSH_K,
 +              [BPF_ALU|BPF_RSH|BPF_X]  = BPF_S_ALU_RSH_X,
 +              [BPF_ALU|BPF_NEG]        = BPF_S_ALU_NEG,
 +              [BPF_LD|BPF_W|BPF_ABS]   = BPF_S_LD_W_ABS,
 +              [BPF_LD|BPF_H|BPF_ABS]   = BPF_S_LD_H_ABS,
 +              [BPF_LD|BPF_B|BPF_ABS]   = BPF_S_LD_B_ABS,
 +              [BPF_LD|BPF_W|BPF_LEN]   = BPF_S_LD_W_LEN,
 +              [BPF_LD|BPF_W|BPF_IND]   = BPF_S_LD_W_IND,
 +              [BPF_LD|BPF_H|BPF_IND]   = BPF_S_LD_H_IND,
 +              [BPF_LD|BPF_B|BPF_IND]   = BPF_S_LD_B_IND,
 +              [BPF_LD|BPF_IMM]         = BPF_S_LD_IMM,
 +              [BPF_LDX|BPF_W|BPF_LEN]  = BPF_S_LDX_W_LEN,
 +              [BPF_LDX|BPF_B|BPF_MSH]  = BPF_S_LDX_B_MSH,
 +              [BPF_LDX|BPF_IMM]        = BPF_S_LDX_IMM,
 +              [BPF_MISC|BPF_TAX]       = BPF_S_MISC_TAX,
 +              [BPF_MISC|BPF_TXA]       = BPF_S_MISC_TXA,
 +              [BPF_RET|BPF_K]          = BPF_S_RET_K,
 +              [BPF_RET|BPF_A]          = BPF_S_RET_A,
 +              [BPF_ALU|BPF_DIV|BPF_K]  = BPF_S_ALU_DIV_K,
 +              [BPF_LD|BPF_MEM]         = BPF_S_LD_MEM,
 +              [BPF_LDX|BPF_MEM]        = BPF_S_LDX_MEM,
 +              [BPF_ST]                 = BPF_S_ST,
 +              [BPF_STX]                = BPF_S_STX,
 +              [BPF_JMP|BPF_JA]         = BPF_S_JMP_JA,
 +              [BPF_JMP|BPF_JEQ|BPF_K]  = BPF_S_JMP_JEQ_K,
 +              [BPF_JMP|BPF_JEQ|BPF_X]  = BPF_S_JMP_JEQ_X,
 +              [BPF_JMP|BPF_JGE|BPF_K]  = BPF_S_JMP_JGE_K,
 +              [BPF_JMP|BPF_JGE|BPF_X]  = BPF_S_JMP_JGE_X,
 +              [BPF_JMP|BPF_JGT|BPF_K]  = BPF_S_JMP_JGT_K,
 +              [BPF_JMP|BPF_JGT|BPF_X]  = BPF_S_JMP_JGT_X,
 +              [BPF_JMP|BPF_JSET|BPF_K] = BPF_S_JMP_JSET_K,
 +              [BPF_JMP|BPF_JSET|BPF_X] = BPF_S_JMP_JSET_X,
 +      };
        int pc;
  
        if (flen == 0 || flen > BPF_MAXINSNS)
  
        /* check the filter code now */
        for (pc = 0; pc < flen; pc++) {
 -              ftest = &filter[pc];
 -
 -              /* Only allow valid instructions */
 -              switch (ftest->code) {
 -              case BPF_ALU|BPF_ADD|BPF_K:
 -                      ftest->code = BPF_S_ALU_ADD_K;
 -                      break;
 -              case BPF_ALU|BPF_ADD|BPF_X:
 -                      ftest->code = BPF_S_ALU_ADD_X;
 -                      break;
 -              case BPF_ALU|BPF_SUB|BPF_K:
 -                      ftest->code = BPF_S_ALU_SUB_K;
 -                      break;
 -              case BPF_ALU|BPF_SUB|BPF_X:
 -                      ftest->code = BPF_S_ALU_SUB_X;
 -                      break;
 -              case BPF_ALU|BPF_MUL|BPF_K:
 -                      ftest->code = BPF_S_ALU_MUL_K;
 -                      break;
 -              case BPF_ALU|BPF_MUL|BPF_X:
 -                      ftest->code = BPF_S_ALU_MUL_X;
 -                      break;
 -              case BPF_ALU|BPF_DIV|BPF_X:
 -                      ftest->code = BPF_S_ALU_DIV_X;
 -                      break;
 -              case BPF_ALU|BPF_AND|BPF_K:
 -                      ftest->code = BPF_S_ALU_AND_K;
 -                      break;
 -              case BPF_ALU|BPF_AND|BPF_X:
 -                      ftest->code = BPF_S_ALU_AND_X;
 -                      break;
 -              case BPF_ALU|BPF_OR|BPF_K:
 -                      ftest->code = BPF_S_ALU_OR_K;
 -                      break;
 -              case BPF_ALU|BPF_OR|BPF_X:
 -                      ftest->code = BPF_S_ALU_OR_X;
 -                      break;
 -              case BPF_ALU|BPF_LSH|BPF_K:
 -                      ftest->code = BPF_S_ALU_LSH_K;
 -                      break;
 -              case BPF_ALU|BPF_LSH|BPF_X:
 -                      ftest->code = BPF_S_ALU_LSH_X;
 -                      break;
 -              case BPF_ALU|BPF_RSH|BPF_K:
 -                      ftest->code = BPF_S_ALU_RSH_K;
 -                      break;
 -              case BPF_ALU|BPF_RSH|BPF_X:
 -                      ftest->code = BPF_S_ALU_RSH_X;
 -                      break;
 -              case BPF_ALU|BPF_NEG:
 -                      ftest->code = BPF_S_ALU_NEG;
 -                      break;
 -              case BPF_LD|BPF_W|BPF_ABS:
 -                      ftest->code = BPF_S_LD_W_ABS;
 -                      break;
 -              case BPF_LD|BPF_H|BPF_ABS:
 -                      ftest->code = BPF_S_LD_H_ABS;
 -                      break;
 -              case BPF_LD|BPF_B|BPF_ABS:
 -                      ftest->code = BPF_S_LD_B_ABS;
 -                      break;
 -              case BPF_LD|BPF_W|BPF_LEN:
 -                      ftest->code = BPF_S_LD_W_LEN;
 -                      break;
 -              case BPF_LD|BPF_W|BPF_IND:
 -                      ftest->code = BPF_S_LD_W_IND;
 -                      break;
 -              case BPF_LD|BPF_H|BPF_IND:
 -                      ftest->code = BPF_S_LD_H_IND;
 -                      break;
 -              case BPF_LD|BPF_B|BPF_IND:
 -                      ftest->code = BPF_S_LD_B_IND;
 -                      break;
 -              case BPF_LD|BPF_IMM:
 -                      ftest->code = BPF_S_LD_IMM;
 -                      break;
 -              case BPF_LDX|BPF_W|BPF_LEN:
 -                      ftest->code = BPF_S_LDX_W_LEN;
 -                      break;
 -              case BPF_LDX|BPF_B|BPF_MSH:
 -                      ftest->code = BPF_S_LDX_B_MSH;
 -                      break;
 -              case BPF_LDX|BPF_IMM:
 -                      ftest->code = BPF_S_LDX_IMM;
 -                      break;
 -              case BPF_MISC|BPF_TAX:
 -                      ftest->code = BPF_S_MISC_TAX;
 -                      break;
 -              case BPF_MISC|BPF_TXA:
 -                      ftest->code = BPF_S_MISC_TXA;
 -                      break;
 -              case BPF_RET|BPF_K:
 -                      ftest->code = BPF_S_RET_K;
 -                      break;
 -              case BPF_RET|BPF_A:
 -                      ftest->code = BPF_S_RET_A;
 -                      break;
 +              struct sock_filter *ftest = &filter[pc];
 +              u16 code = ftest->code;
  
 +              if (code >= ARRAY_SIZE(codes))
 +                      return -EINVAL;
 +              code = codes[code];
 +              if (!code)
 +                      return -EINVAL;
                /* Some instructions need special checks */
 -
 +              switch (code) {
 +              case BPF_S_ALU_DIV_K:
                        /* check for division by zero */
 -              case BPF_ALU|BPF_DIV|BPF_K:
                        if (ftest->k == 0)
                                return -EINVAL;
 -                      ftest->code = BPF_S_ALU_DIV_K;
 -                      break;
 -
 -              /* check for invalid memory addresses */
 -              case BPF_LD|BPF_MEM:
 -                      if (ftest->k >= BPF_MEMWORDS)
 -                              return -EINVAL;
 -                      ftest->code = BPF_S_LD_MEM;
 -                      break;
 -              case BPF_LDX|BPF_MEM:
 -                      if (ftest->k >= BPF_MEMWORDS)
 -                              return -EINVAL;
 -                      ftest->code = BPF_S_LDX_MEM;
 -                      break;
 -              case BPF_ST:
 -                      if (ftest->k >= BPF_MEMWORDS)
 -                              return -EINVAL;
 -                      ftest->code = BPF_S_ST;
 +                      ftest->k = reciprocal_value(ftest->k);
                        break;
 -              case BPF_STX:
 +              case BPF_S_LD_MEM:
 +              case BPF_S_LDX_MEM:
 +              case BPF_S_ST:
 +              case BPF_S_STX:
 +                      /* check for invalid memory addresses */
                        if (ftest->k >= BPF_MEMWORDS)
                                return -EINVAL;
 -                      ftest->code = BPF_S_STX;
                        break;
 -
 -              case BPF_JMP|BPF_JA:
 +              case BPF_S_JMP_JA:
                        /*
                         * Note, the large ftest->k might cause loops.
                         * Compare this with conditional jumps below,
                         */
                        if (ftest->k >= (unsigned)(flen-pc-1))
                                return -EINVAL;
 -                      ftest->code = BPF_S_JMP_JA;
 -                      break;
 -
 -              case BPF_JMP|BPF_JEQ|BPF_K:
 -                      ftest->code = BPF_S_JMP_JEQ_K;
                        break;
 -              case BPF_JMP|BPF_JEQ|BPF_X:
 -                      ftest->code = BPF_S_JMP_JEQ_X;
 -                      break;
 -              case BPF_JMP|BPF_JGE|BPF_K:
 -                      ftest->code = BPF_S_JMP_JGE_K;
 -                      break;
 -              case BPF_JMP|BPF_JGE|BPF_X:
 -                      ftest->code = BPF_S_JMP_JGE_X;
 -                      break;
 -              case BPF_JMP|BPF_JGT|BPF_K:
 -                      ftest->code = BPF_S_JMP_JGT_K;
 -                      break;
 -              case BPF_JMP|BPF_JGT|BPF_X:
 -                      ftest->code = BPF_S_JMP_JGT_X;
 -                      break;
 -              case BPF_JMP|BPF_JSET|BPF_K:
 -                      ftest->code = BPF_S_JMP_JSET_K;
 -                      break;
 -              case BPF_JMP|BPF_JSET|BPF_X:
 -                      ftest->code = BPF_S_JMP_JSET_X;
 -                      break;
 -
 -              default:
 -                      return -EINVAL;
 -              }
 -
 -                      /* for conditionals both must be safe */
 -              switch (ftest->code) {
                case BPF_S_JMP_JEQ_K:
                case BPF_S_JMP_JEQ_X:
                case BPF_S_JMP_JGE_K:
                case BPF_S_JMP_JGT_X:
                case BPF_S_JMP_JSET_X:
                case BPF_S_JMP_JSET_K:
 +                      /* for conditionals both must be safe */
                        if (pc + ftest->jt + 1 >= flen ||
                            pc + ftest->jf + 1 >= flen)
                                return -EINVAL;
 +                      break;
                }
 +              ftest->code = code;
        }
  
        /* last instruction must be a RET code */
        case BPF_S_RET_K:
        case BPF_S_RET_A:
                return 0;
 -              break;
 -              default:
 -                      return -EINVAL;
 -              }
 +      }
 +      return -EINVAL;
  }
  EXPORT_SYMBOL(sk_chk_filter);
  
  /**
-  *    sk_filter_rcu_release: Release a socket filter by rcu_head
+  *    sk_filter_rcu_release - Release a socket filter by rcu_head
   *    @rcu: rcu_head that contains the sk_filter to free
   */
  static void sk_filter_rcu_release(struct rcu_head *rcu)
diff --combined net/ipv4/icmp.c
index 4daebd17b6ede9aa7cb1a50544e978134d986e03,e5d1a44bcbdf04b851d441ea5ebd8fbe44514704..4aa1b7f01ea0c18a5718061fe31eee71f4de883f
@@@ -386,9 -386,10 +386,9 @@@ static void icmp_reply(struct icmp_bxm 
                        daddr = icmp_param->replyopts.faddr;
        }
        {
 -              struct flowi fl = { .nl_u = { .ip4_u =
 -                                            { .daddr = daddr,
 -                                              .saddr = rt->rt_spec_dst,
 -                                              .tos = RT_TOS(ip_hdr(skb)->tos) } },
 +              struct flowi fl = { .fl4_dst= daddr,
 +                                  .fl4_src = rt->rt_spec_dst,
 +                                  .fl4_tos = RT_TOS(ip_hdr(skb)->tos),
                                    .proto = IPPROTO_ICMP };
                security_skb_classify_flow(skb, &fl);
                if (ip_route_output_key(net, &rt, &fl))
@@@ -505,8 -506,8 +505,8 @@@ void icmp_send(struct sk_buff *skb_in, 
                struct net_device *dev = NULL;
  
                rcu_read_lock();
 -              if (rt->fl.iif &&
 -                      net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
 +              if (rt_is_input_route(rt) &&
 +                  net->ipv4.sysctl_icmp_errors_use_inbound_ifaddr)
                        dev = dev_get_by_index_rcu(net, rt->fl.iif);
  
                if (dev)
  
        {
                struct flowi fl = {
 -                      .nl_u = {
 -                              .ip4_u = {
 -                                      .daddr = icmp_param.replyopts.srr ?
 -                                              icmp_param.replyopts.faddr :
 -                                              iph->saddr,
 -                                      .saddr = saddr,
 -                                      .tos = RT_TOS(tos)
 -                              }
 -                      },
 +                      .fl4_dst = icmp_param.replyopts.srr ?
 +                                 icmp_param.replyopts.faddr : iph->saddr,
 +                      .fl4_src = saddr,
 +                      .fl4_tos = RT_TOS(tos),
                        .proto = IPPROTO_ICMP,
 -                      .uli_u = {
 -                              .icmpt = {
 -                                      .type = type,
 -                                      .code = code
 -                              }
 -                      }
 +                      .fl_icmp_type = type,
 +                      .fl_icmp_code = code,
                };
                int err;
                struct rtable *rt2;
                /* No need to clone since we're just using its address. */
                rt2 = rt;
  
+               if (!fl.nl_u.ip4_u.saddr)
+                       fl.nl_u.ip4_u.saddr = rt->rt_src;
                err = xfrm_lookup(net, (struct dst_entry **)&rt, &fl, NULL, 0);
                switch (err) {
                case 0:
diff --combined net/ipv6/addrconf.c
index 470e7acb91dfec637eceaea6adc23b9fbd169b34,2fc35b32df9eacb3c1dcebf153700b5056bc9689..4cf760598c2aa674bb9589b6d6d99c11d1c459fb
  #endif
  
  #define       INFINITY_LIFE_TIME      0xFFFFFFFF
- #define TIME_DELTA(a, b) ((unsigned long)((long)(a) - (long)(b)))
+ static inline u32 cstamp_delta(unsigned long cstamp)
+ {
+       return (cstamp - INITIAL_JIFFIES) * 100UL / HZ;
+ }
  
  #define ADDRCONF_TIMER_FUZZ_MINUS     (HZ > 50 ? HZ/50 : 1)
  #define ADDRCONF_TIMER_FUZZ           (HZ / 4)
@@@ -2754,13 -2758,13 +2758,13 @@@ static int addrconf_ifdown(struct net_d
                        ifa->state = INET6_IFADDR_STATE_DEAD;
                        spin_unlock_bh(&ifa->state_lock);
  
 -                      if (state == INET6_IFADDR_STATE_DEAD) {
 -                              in6_ifa_put(ifa);
 -                      } else {
 +                      if (state != INET6_IFADDR_STATE_DEAD) {
                                __ipv6_ifa_notify(RTM_DELADDR, ifa);
                                atomic_notifier_call_chain(&inet6addr_chain,
                                                           NETDEV_DOWN, ifa);
                        }
 +
 +                      in6_ifa_put(ifa);
                        write_lock_bh(&idev->lock);
                }
        }
@@@ -3444,10 -3448,8 +3448,8 @@@ static int put_cacheinfo(struct sk_buf
  {
        struct ifa_cacheinfo ci;
  
-       ci.cstamp = (u32)(TIME_DELTA(cstamp, INITIAL_JIFFIES) / HZ * 100
-                       + TIME_DELTA(cstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
-       ci.tstamp = (u32)(TIME_DELTA(tstamp, INITIAL_JIFFIES) / HZ * 100
-                       + TIME_DELTA(tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
+       ci.cstamp = cstamp_delta(cstamp);
+       ci.tstamp = cstamp_delta(tstamp);
        ci.ifa_prefered = preferred;
        ci.ifa_valid = valid;
  
@@@ -3798,8 -3800,10 +3800,10 @@@ static inline void ipv6_store_devconf(s
        array[DEVCONF_AUTOCONF] = cnf->autoconf;
        array[DEVCONF_DAD_TRANSMITS] = cnf->dad_transmits;
        array[DEVCONF_RTR_SOLICITS] = cnf->rtr_solicits;
-       array[DEVCONF_RTR_SOLICIT_INTERVAL] = cnf->rtr_solicit_interval;
-       array[DEVCONF_RTR_SOLICIT_DELAY] = cnf->rtr_solicit_delay;
+       array[DEVCONF_RTR_SOLICIT_INTERVAL] =
+               jiffies_to_msecs(cnf->rtr_solicit_interval);
+       array[DEVCONF_RTR_SOLICIT_DELAY] =
+               jiffies_to_msecs(cnf->rtr_solicit_delay);
        array[DEVCONF_FORCE_MLD_VERSION] = cnf->force_mld_version;
  #ifdef CONFIG_IPV6_PRIVACY
        array[DEVCONF_USE_TEMPADDR] = cnf->use_tempaddr;
        array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
  #ifdef CONFIG_IPV6_ROUTER_PREF
        array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
-       array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
+       array[DEVCONF_RTR_PROBE_INTERVAL] =
+               jiffies_to_msecs(cnf->rtr_probe_interval);
  #ifdef CONFIG_IPV6_ROUTE_INFO
        array[DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN] = cnf->accept_ra_rt_info_max_plen;
  #endif
        array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
  }
  
 +static inline size_t inet6_ifla6_size(void)
 +{
 +      return nla_total_size(4) /* IFLA_INET6_FLAGS */
 +           + nla_total_size(sizeof(struct ifla_cacheinfo))
 +           + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
 +           + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
 +           + nla_total_size(ICMP6_MIB_MAX * 8); /* IFLA_INET6_ICMP6STATS */
 +}
 +
  static inline size_t inet6_if_nlmsg_size(void)
  {
        return NLMSG_ALIGN(sizeof(struct ifinfomsg))
               + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
               + nla_total_size(4) /* IFLA_MTU */
               + nla_total_size(4) /* IFLA_LINK */
 -             + nla_total_size( /* IFLA_PROTINFO */
 -                      nla_total_size(4) /* IFLA_INET6_FLAGS */
 -                      + nla_total_size(sizeof(struct ifla_cacheinfo))
 -                      + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
 -                      + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
 -                      + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
 -               );
 +             + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */
  }
  
  static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib,
@@@ -3894,76 -3896,15 +3899,75 @@@ static void snmp6_fill_stats(u64 *stats
        }
  }
  
-       ci.tstamp = (__u32)(TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) / HZ * 100
-                   + TIME_DELTA(idev->tstamp, INITIAL_JIFFIES) % HZ * 100 / HZ);
-       ci.reachable_time = idev->nd_parms->reachable_time;
-       ci.retrans_time = idev->nd_parms->retrans_time;
 +static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
 +{
 +      struct nlattr *nla;
 +      struct ifla_cacheinfo ci;
 +
 +      NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
 +
 +      ci.max_reasm_len = IPV6_MAXPLEN;
++      ci.tstamp = cstamp_delta(idev->tstamp);
++      ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
++      ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time);
 +      NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
 +
 +      nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
 +      if (nla == NULL)
 +              goto nla_put_failure;
 +      ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
 +
 +      /* XXX - MC not implemented */
 +
 +      nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
 +      if (nla == NULL)
 +              goto nla_put_failure;
 +      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
 +
 +      nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
 +      if (nla == NULL)
 +              goto nla_put_failure;
 +      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
 +
 +      return 0;
 +
 +nla_put_failure:
 +      return -EMSGSIZE;
 +}
 +
 +static size_t inet6_get_link_af_size(const struct net_device *dev)
 +{
 +      if (!__in6_dev_get(dev))
 +              return 0;
 +
 +      return inet6_ifla6_size();
 +}
 +
 +static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
 +{
 +      struct inet6_dev *idev = __in6_dev_get(dev);
 +
 +      if (!idev)
 +              return -ENODATA;
 +
 +      if (inet6_fill_ifla6_attrs(skb, idev) < 0)
 +              return -EMSGSIZE;
 +
 +      return 0;
 +}
 +
 +static int inet6_parse_link_af(struct net_device *dev, const struct nlattr *nla)
 +{
 +      return -EOPNOTSUPP;
 +}
 +
  static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
                             u32 pid, u32 seq, int event, unsigned int flags)
  {
        struct net_device *dev = idev->dev;
 -      struct nlattr *nla;
        struct ifinfomsg *hdr;
        struct nlmsghdr *nlh;
        void *protoinfo;
 -      struct ifla_cacheinfo ci;
  
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
        if (nlh == NULL)
        if (protoinfo == NULL)
                goto nla_put_failure;
  
 -      NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags);
 -
 -      ci.max_reasm_len = IPV6_MAXPLEN;
 -      ci.tstamp = cstamp_delta(idev->tstamp);
 -      ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
 -      ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time);
 -      NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci);
 -
 -      nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
 -      if (nla == NULL)
 -              goto nla_put_failure;
 -      ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla));
 -
 -      /* XXX - MC not implemented */
 -
 -      nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64));
 -      if (nla == NULL)
 -              goto nla_put_failure;
 -      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla));
 -
 -      nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64));
 -      if (nla == NULL)
 +      if (inet6_fill_ifla6_attrs(skb, idev) < 0)
                goto nla_put_failure;
 -      snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
  
        nla_nest_end(skb, protoinfo);
        return nlmsg_end(skb, nlh);
@@@ -4662,13 -4625,6 +4666,13 @@@ int unregister_inet6addr_notifier(struc
  }
  EXPORT_SYMBOL(unregister_inet6addr_notifier);
  
 +static struct rtnl_af_ops inet6_ops = {
 +      .family           = AF_INET6,
 +      .fill_link_af     = inet6_fill_link_af,
 +      .get_link_af_size = inet6_get_link_af_size,
 +      .parse_link_af    = inet6_parse_link_af,
 +};
 +
  /*
   *    Init / cleanup code
   */
@@@ -4720,10 -4676,6 +4724,10 @@@ int __init addrconf_init(void
  
        addrconf_verify(0);
  
 +      err = rtnl_af_register(&inet6_ops);
 +      if (err < 0)
 +              goto errout_af;
 +
        err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo);
        if (err < 0)
                goto errout;
  
        return 0;
  errout:
 +      rtnl_af_unregister(&inet6_ops);
 +errout_af:
        unregister_netdevice_notifier(&ipv6_dev_notf);
  errlo:
        unregister_pernet_subsys(&addrconf_ops);
@@@ -4761,8 -4711,6 +4765,8 @@@ void addrconf_cleanup(void
  
        rtnl_lock();
  
 +      __rtnl_af_unregister(&inet6_ops);
 +
        /* clean dev list */
        for_each_netdev(&init_net, dev) {
                if (__in6_dev_get(dev) == NULL)