diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-12 11:12:06 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-11-12 11:12:06 -0800 |
commit | e697b8d13ede3893724898d983eff3f8c9183643 (patch) | |
tree | 0144d2d98d33e92a1d93739f0db12997c000d456 | |
parent | 46015977e70f672ae6b20a1b5fb1e361208365ba (diff) | |
parent | 2994c63863ac350c4c8c6a65d8110749c2abb95c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (39 commits)
[INET]: Small possible memory leak in FIB rules
[NETNS]: init dev_base_lock only once
[UNIX]: The unix_nr_socks limit can be exceeded
[AF_UNIX]: Convert socks to unix_socks in scan_inflight, not in callbacks
[AF_UNIX]: Make unix_tot_inflight counter non-atomic
[AF_PACKET]: Allow multicast traffic to be caught by ORIGDEV when bonded
ssb: Fix PCMCIA-host lowlevel bus access
mac80211: fix MAC80211_RCSIMPLE Kconfig
mac80211: make "decrypt failed" messages conditional upon MAC80211_DEBUG
mac80211: use IW_AUTH_PRIVACY_INVOKED rather than IW_AUTH_KEY_MGMT
mac80211: remove unused driver ops
mac80211: remove ieee80211_common.h
softmac: MAINTAINERS update
rfkill: Fix sparse warning
rfkill: Use mutex_lock() at register and add sanity check
iwlwifi: select proper rate control algorithm
mac80211: allow driver to ask for a rate control algorithm
mac80211: don't allow registering the same rate control twice
rfkill: Use subsys_initcall
mac80211: make simple rate control algorithm built-in
...
45 files changed, 380 insertions, 428 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 6a970272623..cad0882754a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3454,15 +3454,10 @@ L: lm-sensors@lm-sensors.org S: Maintained SOFTMAC LAYER (IEEE 802.11) -P: Johannes Berg -M: johannes@sipsolutions.net -P: Joe Jezak -M: josejx@gentoo.org P: Daniel Drake M: dsd@gentoo.org -W: http://softmac.sipsolutions.net/ L: linux-wireless@vger.kernel.org -S: Maintained +S: Obsolete SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4f22a7174ca..be7c9f42a34 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -8354,6 +8354,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_IEEE80211_DEV(hw, &pdev->dev); + hw->rate_control_algorithm = "iwl-3945-rs"; + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d60adcb9bd4..6757c6c1b25 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8955,6 +8955,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_IEEE80211_DEV(hw, &pdev->dev); + hw->rate_control_algorithm = "iwl-4965-rs"; + IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index c12a741b557..85a20546e82 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -440,6 +440,7 @@ static int ssb_devices_register(struct ssb_bus *bus) break; case SSB_BUSTYPE_PCMCIA: #ifdef CONFIG_SSB_PCMCIAHOST + sdev->irq = bus->host_pcmcia->irq.AssignedIRQ; dev->parent = &bus->host_pcmcia->dev; #endif break; @@ -1147,7 +1148,10 @@ static int __init ssb_modinit(void) return err; } -subsys_initcall(ssb_modinit); +/* ssb must be initialized after PCI but before the ssb drivers. + * That means we must use some initcall between subsys_initcall + * and device_initcall. */ +fs_initcall(ssb_modinit); static void __exit ssb_modexit(void) { diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index b6abee846f0..bb44a76b3eb 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -63,17 +63,17 @@ int ssb_pcmcia_switch_coreidx(struct ssb_bus *bus, err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= (reg.Value & 0xF) << 12; + read_addr |= ((u32)(reg.Value & 0x0F)) << 12; reg.Offset = 0x30; err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= reg.Value << 16; + read_addr |= ((u32)reg.Value) << 16; reg.Offset = 0x32; err = pcmcia_access_configuration_register(pdev, ®); if (err != CS_SUCCESS) goto error; - read_addr |= reg.Value << 24; + read_addr |= ((u32)reg.Value) << 24; cur_core = (read_addr - SSB_ENUM_BASE) / SSB_CORE_SIZE; if (cur_core == coreidx) @@ -152,28 +152,29 @@ error: goto out_unlock; } -/* These are the main device register access functions. - * do_select_core is inline to have the likely hotpath inline. - * All unlikely codepaths are out-of-line. */ -static inline int do_select_core(struct ssb_bus *bus, - struct ssb_device *dev, - u16 *offset) +static int select_core_and_segment(struct ssb_device *dev, + u16 *offset) { + struct ssb_bus *bus = dev->bus; int err; - u8 need_seg = (*offset >= 0x800) ? 1 : 0; + u8 need_segment; + + if (*offset >= 0x800) { + *offset -= 0x800; + need_segment = 1; + } else + need_segment = 0; if (unlikely(dev != bus->mapped_device)) { err = ssb_pcmcia_switch_core(bus, dev); if (unlikely(err)) return err; } - if (unlikely(need_seg != bus->mapped_pcmcia_seg)) { - err = ssb_pcmcia_switch_segment(bus, need_seg); + if (unlikely(need_segment != bus->mapped_pcmcia_seg)) { + err = ssb_pcmcia_switch_segment(bus, need_segment); if (unlikely(err)) return err; } - if (need_seg == 1) - *offset -= 0x800; return 0; } @@ -181,32 +182,31 @@ static inline int do_select_core(struct ssb_bus *bus, static u16 ssb_pcmcia_read16(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u16 x; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return 0xFFFF; - x = readw(bus->mmio + offset); - return x; + return readw(bus->mmio + offset); } static u32 ssb_pcmcia_read32(struct ssb_device *dev, u16 offset) { struct ssb_bus *bus = dev->bus; - u32 x; + u32 lo, hi; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return 0xFFFFFFFF; - x = readl(bus->mmio + offset); + lo = readw(bus->mmio + offset); + hi = readw(bus->mmio + offset + 2); - return x; + return (lo | (hi << 16)); } static void ssb_pcmcia_write16(struct ssb_device *dev, u16 offset, u16 value) { struct ssb_bus *bus = dev->bus; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return; writew(value, bus->mmio + offset); } @@ -215,12 +215,12 @@ static void ssb_pcmcia_write32(struct ssb_device *dev, u16 offset, u32 value) { struct ssb_bus *bus = dev->bus; - if (unlikely(do_select_core(bus, dev, &offset))) + if (unlikely(select_core_and_segment(dev, &offset))) return; - readw(bus->mmio + offset); - writew(value >> 16, bus->mmio + offset + 2); - readw(bus->mmio + offset); - writew(value, bus->mmio + offset); + writeb((value & 0xFF000000) >> 24, bus->mmio + offset + 3); + writeb((value & 0x00FF0000) >> 16, bus->mmio + offset + 2); + writeb((value & 0x0000FF00) >> 8, bus->mmio + offset + 1); + writeb((value & 0x000000FF) >> 0, bus->mmio + offset + 0); } /* Not "static", as it's used in main.c */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 94e49915a8c..91140fe8c11 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -387,7 +387,9 @@ extern void skb_truesize_bug(struct sk_buff *skb); static inline void skb_truesize_check(struct sk_buff *skb) { - if (unlikely((int)skb->truesize < sizeof(struct sk_buff) + skb->len)) + int len = sizeof(struct sk_buff) + skb->len; + + if (unlikely((int)skb->truesize < len)) skb_truesize_bug(skb); } diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 0864a775de2..a1c805d7f48 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -12,7 +12,7 @@ extern void unix_gc(void); #define UNIX_HASH_SIZE 256 -extern atomic_t unix_tot_inflight; +extern unsigned int unix_tot_inflight; struct unix_address { atomic_t refcnt; diff --git a/include/net/dst.h b/include/net/dst.h index e9ff4a4caef..2f65e894b82 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -143,6 +143,13 @@ static inline void dst_hold(struct dst_entry * dst) atomic_inc(&dst->__refcnt); } +static inline void dst_use(struct dst_entry *dst, unsigned long time) +{ + dst_hold(dst); + dst->__use++; + dst->lastuse = time; +} + static inline struct dst_entry * dst_clone(struct dst_entry * dst) { diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 017aebd9068..41a301e3864 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -107,4 +107,7 @@ extern int fib_rules_unregister(struct fib_rules_ops *); extern int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags, struct fib_lookup_arg *); +extern int fib_default_rule_add(struct fib_rules_ops *, + u32 pref, u32 table, + u32 flags); #endif diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 8461cda3749..469216d9366 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -23,6 +23,7 @@ #include <linux/spinlock.h> #include <linux/types.h> #include <linux/wait.h> +#include <linux/vmalloc.h> #include <net/inet_connection_sock.h> #include <net/inet_sock.h> diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 5fcc4c10434..17b60391fcd 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -706,11 +706,16 @@ enum ieee80211_hw_flags { * * @queues: number of available hardware transmit queues for * data packets. WMM/QoS requires at least four. + * + * @rate_control_algorithm: rate control algorithm for this hardware. + * If unset (NULL), the default algorithm will be used. Must be + * set before calling ieee80211_register_hw(). */ struct ieee80211_hw { struct ieee80211_conf conf; struct wiphy *wiphy; struct workqueue_struct *workqueue; + const char *rate_control_algorithm; void *priv; u32 flags; unsigned int extra_tx_headroom; @@ -936,27 +941,11 @@ enum ieee80211_erp_change_flags { * and remove_interface calls, i.e. while the interface with the * given local_address is enabled. * - * @set_ieee8021x: Enable/disable IEEE 802.1X. This item requests wlan card - * to pass unencrypted EAPOL-Key frames even when encryption is - * configured. If the wlan card does not require such a configuration, - * this function pointer can be set to NULL. - * - * @set_port_auth: Set port authorization state (IEEE 802.1X PAE) to be - * authorized (@authorized=1) or unauthorized (=0). This function can be - * used if the wlan hardware or low-level driver implements PAE. - * mac80211 will filter frames based on authorization state in any case, - * so this function pointer can be NULL if low-level driver does not - * require event notification about port state changes. - * * @hw_scan: Ask the hardware to service the scan request, no need to start * the scan state machine in stack. * * @get_stats: return low-level statistics * - * @set_privacy_invoked: For devices that generate their own beacons and probe - * response or association responses this updates the state of privacy_invoked - * returns 0 for success or an error number. - * * @get_sequence_counter: For devices that have internal sequence counters this * callback allows mac80211 to access the current value of a counter. * This callback seems not well-defined, tell us if you need it. @@ -1029,14 +1018,9 @@ struct ieee80211_ops { int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_address, const u8 *address, struct ieee80211_key_conf *key); - int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x); - int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr, - int authorized); int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); int (*get_stats)(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); - int (*set_privacy_invoked)(struct ieee80211_hw *hw, - int privacy_invoked); int (*get_sequence_counter)(struct ieee80211_hw *hw, u8* addr, u8 keyidx, u8 txrx, u32* iv32, u16* iv16); diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 1037748c14d..6567213959c 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -376,6 +376,7 @@ void vlan_setup(struct net_device *new_dev) new_dev->init = vlan_dev_init; new_dev->open = vlan_dev_open; new_dev->stop = vlan_dev_stop; + new_dev->set_mac_address = vlan_set_mac_address; new_dev->set_multicast_list = vlan_dev_set_multicast_list; new_dev->change_rx_flags = vlan_change_rx_flags; new_dev->destructor = free_netdev; @@ -636,6 +637,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, if (!vlandev) continue; + flgs = vlandev->flags; + if (!(flgs & IFF_UP)) + continue; + vlan_sync_address(dev, vlandev); } break; diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index cf4a80d06b3..2cd1393073e 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -60,6 +60,7 @@ int vlan_dev_hwaccel_hard_start_xmit(struct sk_buff *skb, struct net_device *dev int vlan_dev_change_mtu(struct net_device *dev, int new_mtu); int vlan_dev_open(struct net_device* dev); int vlan_dev_stop(struct net_device* dev); +int vlan_set_mac_address(struct net_device *dev, void *p); int vlan_dev_ioctl(struct net_device* dev, struct ifreq *ifr, int cmd); void vlan_dev_set_ingress_priority(const struct net_device *dev, u32 skb_prio, short vlan_prio); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 1a1740aa9a8..7a36878241d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -665,6 +665,32 @@ int vlan_dev_stop(struct net_device *dev) return 0; } +int vlan_set_mac_address(struct net_device *dev, void *p) +{ + struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; + struct sockaddr *addr = p; + int err; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + if (!(dev->flags & IFF_UP)) + goto out; + + if (compare_ether_addr(addr->sa_data, real_dev->dev_addr)) { + err = dev_unicast_add(real_dev, addr->sa_data, ETH_ALEN); + if (err < 0) + return err; + } + + if (compare_ether_addr(dev->dev_addr, real_dev->dev_addr)) + dev_unicast_delete(real_dev, dev->dev_addr, ETH_ALEN); + +out: + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + return 0; +} + int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { struct net_device *real_dev = VLAN_DEV_INFO(dev)->real_dev; diff --git a/net/core/dev.c b/net/core/dev.c index be6cedab5aa..dd7e30754cb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4330,7 +4330,6 @@ static struct hlist_head *netdev_create_hash(void) static int __net_init netdev_init(struct net *net) { INIT_LIST_HEAD(&net->dev_base_head); - rwlock_init(&dev_base_lock); net->dev_name_head = netdev_create_hash(); if (net->dev_name_head == NULL) diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c index ae354057d84..647973daca2 100644 --- a/net/core/dev_mcast.c +++ b/net/core/dev_mcast.c @@ -168,13 +168,13 @@ void dev_mc_unsync(struct net_device *to, struct net_device *from) da = from->mc_list; while (da != NULL) { next = da->next; - if (!da->da_synced) - continue; - __dev_addr_delete(&to->mc_list, &to->mc_count, - da->da_addr, da->da_addrlen, 0); - da->da_synced = 0; - __dev_addr_delete(&from->mc_list, &from->mc_count, - da->da_addr, da->da_addrlen, 0); + if (da->da_synced) { + __dev_addr_delete(&to->mc_list, &to->mc_count, + da->da_addr, da->da_addrlen, 0); + da->da_synced = 0; + __dev_addr_delete(&from->mc_list, &from->mc_count, + da->da_addr, da->da_addrlen, 0); + } da = next; } __dev_set_rx_mode(to); diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 13de6f53f09..848132b6cb7 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -18,6 +18,28 @@ static LIST_HEAD(rules_ops); static DEFINE_SPINLOCK(rules_mod_lock); +int fib_default_rule_add(struct fib_rules_ops *ops, + u32 pref, u32 table, u32 flags) +{ + struct fib_rule *r; + + r = kzalloc(ops->rule_size, GFP_KERNEL); + if (r == NULL) + return -ENOMEM; + + atomic_set(&r->refcnt, 1); + r->action = FR_ACT_TO_TBL; + r->pref = pref; + r->table = table; + r->flags = flags; + + /* The lock is not required here, the list in unreacheable + * at the moment this function is called */ + list_add_tail(&r->list, &ops->rules_list); + return 0; +} +EXPORT_SYMBOL(fib_default_rule_add); + static void notify_rule_change(int event, struct fib_rule *rule, struct fib_rules_ops *ops, struct nlmsghdr *nlh, u32 pid); diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 97eee5e8fbb..66663e5d7ac 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -293,9 +293,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route * dn_rt_hash_table[hash].chain); rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth); - rth->u.dst.__use++; - dst_hold(&rth->u.dst); - rth->u.dst.lastuse = now; + dst_use(&rth->u.dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); dnrt_drop(rt); @@ -308,9 +306,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned hash, struct dn_route * rcu_assign_pointer(rt->u.dst.dn_next, dn_rt_hash_table[hash].chain); rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt); - dst_hold(&rt->u.dst); - rt->u.dst.__use++; - rt->u.dst.lastuse = now; + dst_use(&rt->u.dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); *rp = rt; return 0; @@ -1182,9 +1178,7 @@ static int __dn_route_output_key(struct dst_entry **pprt, const struct flowi *fl (flp->mark == rt->fl.mark) && (rt->fl.iif == 0) && (rt->fl.oif == flp->oif)) { - rt->u.dst.lastuse = jiffies; - dst_hold(&rt->u.dst); - rt->u.dst.__use++; + dst_use(&rt->u.dst, jiffies); rcu_read_unlock_bh(); *pprt = &rt->u.dst; return 0; @@ -1456,9 +1450,7 @@ int dn_route_input(struct sk_buff *skb) (rt->fl.oif == 0) && (rt->fl.mark == skb->mark) && (rt->fl.iif == cb->iif)) { - rt->u.dst.lastuse = jiffies; - dst_hold(&rt->u.dst); - rt->u.dst.__use++; + dst_use(&rt->u.dst, jiffies); rcu_read_unlock(); skb->dst = (struct dst_entry *)rt; return 0; diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c index ddd3f04f091..ffebea04cc9 100644 --- a/net/decnet/dn_rules.c +++ b/net/decnet/dn_rules.c @@ -48,15 +48,6 @@ struct dn_fib_rule u8 flags; }; -static struct dn_fib_rule default_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7fff, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - }, -}; - int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res) { @@ -262,8 +253,8 @@ static struct fib_rules_ops dn_fib_rules_ops = { void __init dn_fib_rules_init(void) { - list_add_tail(&default_rule.common.list, - &dn_fib_rules_ops.rules_list); + BUG_ON(fib_default_rule_add(&dn_fib_rules_ops, 0x7fff, + RT_TABLE_MAIN, 0)); fib_rules_register(&dn_fib_rules_ops); } diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index ac36767b56e..e01b59aedc5 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -470,7 +470,7 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, { struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct iw_mlme *mlme = (struct iw_mlme *)extra; - u16 reason = cpu_to_le16(mlme->reason_code); + u16 reason = mlme->reason_code; struct ieee80211softmac_network *net; int err = -EINVAL; diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index f16839c6a72..a0ada3a8d8d 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -49,33 +49,6 @@ struct fib4_rule #endif }; -static struct fib4_rule default_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFF, - .table = RT_TABLE_DEFAULT, - .action = FR_ACT_TO_TBL, - }, -}; - -static struct fib4_rule main_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .pref = 0x7FFE, - .table = RT_TABLE_MAIN, - .action = FR_ACT_TO_TBL, - }, -}; - -static struct fib4_rule local_rule = { - .common = { - .refcnt = ATOMIC_INIT(2), - .table = RT_TABLE_LOCAL, - .action = FR_ACT_TO_TBL, - .flags = FIB_RULE_PERMANENT, - }, -}; - #ifdef CONFIG_NET_CLS_ROUTE u32 fib_rules_tclass(struct fib_result *res) { @@ -319,11 +292,27 @@ static struct fib_rules_ops fib4_rules_ops = { .owner = THIS_MODULE, }; -void __init fib4_rules_init(void) +static int __init fib_default_rules_init(void) { - list_add_tail(&local_rule.common.list, &fib4_rules_ops.rules_list); - list_add_tail(&main_rule.common.list, &fib4_rules_ops.rules_list); - list_add_tail(&default_rule.common.list, &fib4_rules_ops.rules_list); + int err; + + err = fib_default_rule_add(&fib4_rules_ops, 0, + RT_TABLE_LOCAL, FIB_RULE_PERMANENT); + if (err < 0) + return err; + err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE, + RT_TABLE_MAIN, 0); + if (err < 0) + return err; + err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF, + RT_TABLE_DEFAULT, 0); + if (err < 0) + return err; + return 0; +} +void __init fib4_rules_init(void) +{ + BUG_ON(fib_default_rules_init()); fib_rules_register(&fib4_rules_ops); } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 21b12de9e65..45651834e1e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -851,9 +851,7 @@ restart: */ rcu_assign_pointer(rt_hash_table[hash].chain, rth); - rth->u.dst.__use++; - dst_hold(&rth->u.dst); - rth->u.dst.lastuse = now; + dst_use(&rth->u.dst, now); spin_unlock_bh(rt_hash_lock_addr(hash)); rt_drop(rt); @@ -1813,11 +1811,6 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, goto martian_destination; err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos); - if (err == -ENOBUFS) |