Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 6 May 2008 14:49:20 +0000 (07:49 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 6 May 2008 14:49:20 +0000 (07:49 -0700)
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  net_cls_act: act_simple dont ignore realloc code
  iwlwifi: make IWLWIFI a tristate
  Revert "atm: Do not free already unregistered net device."
  dccp: return -EINVAL on invalid feature length
  irda: fix !PNP support for drivers/net/irda/smsc-ircc2.c
  irda: fix !PNP support in drivers/net/irda/nsc-ircc.c
  net_cls_act: Make act_simple use of netlink policy.
  ip: Use inline function dst_metric() instead of direct access to dst->metric[]
  ip: Make use of the inline function dst_metric_locked()
  atm: Bad locking on br2684_devs modifications.
  atm: Do not free already unregistered net device.
  mac80211: Do not free net device after it is unregistered.
  bridge: Consolidate error paths in br_add_bridge().
  bridge: Net device leak in br_add_bridge().
  niu: Fix probing regression for maramba on-board chips.
  lapbeth: Release ->ethdev when unregistering device.
  xfrm: convert empty xfrm_audit_* macros to functions
  net: Fix useless comment reference loop.
  sch_htb: remove from event queue in htb_parent_to_leaf()

18 files changed:
drivers/net/irda/nsc-ircc.c
drivers/net/irda/smsc-ircc2.c
drivers/net/niu.c
drivers/net/wan/lapbether.c
drivers/net/wireless/iwlwifi/Kconfig
include/net/ip.h
include/net/xfrm.h
net/atm/br2684.c
net/bridge/br_if.c
net/core/skbuff.c
net/dccp/feat.c
net/decnet/dn_route.c
net/ipv4/route.c
net/ipv4/tcp_input.c
net/ipv6/route.c
net/mac80211/main.c
net/sched/act_simple.c
net/sched/sch_htb.c

index a873d2b..a7714da 100644 (file)
@@ -100,7 +100,9 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
 static int nsc_ircc_init_39x(nsc_chip_t *chip, chipio_t *info);
+#ifdef CONFIG_PNP
 static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id);
+#endif
 
 /* These are the known NSC chips */
 static nsc_chip_t chips[] = {
@@ -156,9 +158,11 @@ static const struct pnp_device_id nsc_ircc_pnp_table[] = {
 MODULE_DEVICE_TABLE(pnp, nsc_ircc_pnp_table);
 
 static struct pnp_driver nsc_ircc_pnp_driver = {
+#ifdef CONFIG_PNP
        .name = "nsc-ircc",
        .id_table = nsc_ircc_pnp_table,
        .probe = nsc_ircc_pnp_probe,
+#endif
 };
 
 /* Some prototypes */
@@ -916,6 +920,7 @@ static int nsc_ircc_probe_39x(nsc_chip_t *chip, chipio_t *info)
        return 0;
 }
 
+#ifdef CONFIG_PNP
 /* PNP probing */
 static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id)
 {
@@ -952,6 +957,7 @@ static int nsc_ircc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *i
 
        return 0;
 }
+#endif
 
 /*
  * Function nsc_ircc_setup (info)
index 1f26da7..cfe0194 100644 (file)
@@ -376,6 +376,7 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
 
 static int pnp_driver_registered;
 
+#ifdef CONFIG_PNP
 static int __init smsc_ircc_pnp_probe(struct pnp_dev *dev,
                                      const struct pnp_device_id *dev_id)
 {
@@ -402,7 +403,9 @@ static struct pnp_driver smsc_ircc_pnp_driver = {
        .id_table       = smsc_ircc_pnp_table,
        .probe          = smsc_ircc_pnp_probe,
 };
-
+#else /* CONFIG_PNP */
+static struct pnp_driver smsc_ircc_pnp_driver;
+#endif
 
 /*******************************************************************************
  *
index 4009c4c..57cfd72 100644 (file)
@@ -1,6 +1,6 @@
 /* niu.c: Neptune ethernet driver.
  *
- * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/module.h>
@@ -33,8 +33,8 @@
 
 #define DRV_MODULE_NAME                "niu"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "0.8"
-#define DRV_MODULE_RELDATE     "April 24, 2008"
+#define DRV_MODULE_VERSION     "0.9"
+#define DRV_MODULE_RELDATE     "May 4, 2008"
 
 static char version[] __devinitdata =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -7264,8 +7264,11 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
                                parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
                                        ESPC_NUM_PORTS_MACS_VAL;
 
+                               /* All of the current probing methods fail on
+                                * Maramba on-board parts.
+                                */
                                if (!parent->num_ports)
-                                       return -ENODEV;
+                                       parent->num_ports = 4;
                        }
                }
        }
index b5860b9..24fd613 100644 (file)
@@ -459,6 +459,7 @@ static void __exit lapbeth_cleanup_driver(void)
        list_for_each_safe(entry, tmp, &lapbeth_devices) {
                lapbeth = list_entry(entry, struct lapbethdev, node);
 
+               dev_put(lapbeth->ethdev);
                unregister_netdevice(lapbeth->axdev);
        }
        rtnl_unlock();
index d5b7a76..62fb89d 100644 (file)
@@ -1,6 +1,5 @@
 config IWLWIFI
-       bool
-       default n
+       tristate
 
 config IWLCORE
        tristate "Intel Wireless Wifi Core"
index 6d7bcd5..3b40bc2 100644 (file)
@@ -210,7 +210,7 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst)
 {
        return (inet_sk(sk)->pmtudisc == IP_PMTUDISC_DO ||
                (inet_sk(sk)->pmtudisc == IP_PMTUDISC_WANT &&
-                !(dst_metric(dst, RTAX_LOCK)&(1<<RTAX_MTU))));
+                !(dst_metric_locked(dst, RTAX_MTU))));
 }
 
 extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more);
index d1350bc..2933d74 100644 (file)
@@ -648,14 +648,46 @@ extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
 extern void xfrm_audit_state_icvfail(struct xfrm_state *x,
                                     struct sk_buff *skb, u8 proto);
 #else
-#define xfrm_audit_policy_add(x, r, a, se, s)  do { ; } while (0)
-#define xfrm_audit_policy_delete(x, r, a, se, s)       do { ; } while (0)
-#define xfrm_audit_state_add(x, r, a, se, s)   do { ; } while (0)
-#define xfrm_audit_state_delete(x, r, a, se, s)        do { ; } while (0)
-#define xfrm_audit_state_replay_overflow(x, s) do { ; } while (0)
-#define xfrm_audit_state_notfound_simple(s, f) do { ; } while (0)
-#define xfrm_audit_state_notfound(s, f, sp, sq)        do { ; } while (0)
-#define xfrm_audit_state_icvfail(x, s, p)      do { ; } while (0)
+
+static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
+                                 u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
+                                 u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_add(struct xfrm_state *x, int result,
+                                u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_delete(struct xfrm_state *x, int result,
+                                   u32 auid, u32 ses, u32 secid)
+{
+}
+
+static inline void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
+                                            struct sk_buff *skb)
+{
+}
+
+static inline void xfrm_audit_state_notfound_simple(struct sk_buff *skb,
+                                     u16 family)
+{
+}
+
+static inline void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family,
+                                     __be32 net_spi, __be32 net_seq)
+{
+}
+
+static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
+                                    struct sk_buff *skb, u8 proto)
+{
+}
 #endif /* CONFIG_AUDITSYSCALL */
 
 static inline void xfrm_pol_hold(struct xfrm_policy *policy)
index 1b22806..9d52ebf 100644 (file)
@@ -346,9 +346,9 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
                /* skb==NULL means VCC is being destroyed */
                br2684_close_vcc(brvcc);
                if (list_empty(&brdev->brvccs)) {
-                       read_lock(&devs_lock);
+                       write_lock_irq(&devs_lock);
                        list_del(&brdev->br2684_devs);
-                       read_unlock(&devs_lock);
+                       write_unlock_irq(&devs_lock);
                        unregister_netdev(net_dev);
                        free_netdev(net_dev);
                }
index 77a981a..c2397f5 100644 (file)
@@ -273,15 +273,13 @@ int br_add_bridge(const char *name)
        rtnl_lock();
        if (strchr(dev->name, '%')) {
                ret = dev_alloc_name(dev, dev->name);
-               if (ret < 0) {
-                       free_netdev(dev);
-                       goto out;
-               }
+               if (ret < 0)
+                       goto out_free;
        }
 
        ret = register_netdevice(dev);
        if (ret)
-               goto out;
+               goto out_free;
 
        ret = br_sysfs_addbr(dev);
        if (ret)
@@ -289,6 +287,10 @@ int br_add_bridge(const char *name)
  out:
        rtnl_unlock();
        return ret;
+
+out_free:
+       free_netdev(dev);
+       goto out;
 }
 
 int br_del_bridge(const char *name)
index 4fe605f..5c459f2 100644 (file)
@@ -200,7 +200,9 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
                goto nodata;
 
        /*
-        * See comment in sk_buff definition, just before the 'tail' member
+        * Only clear those fields we need to clear, not those that we will
+        * actually initialise below. Hence, don't put any more fields after
+        * the tail pointer in struct sk_buff!
         */
        memset(skb, 0, offsetof(struct sk_buff, tail));
        skb->truesize = size + sizeof(struct sk_buff);
index 4a4f6ce..933a0ec 100644 (file)
@@ -32,7 +32,7 @@ int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature,
 
        if (len > 3) {
                DCCP_WARN("invalid length %d\n", len);
-               return 1;
+               return -EINVAL;
        }
        /* XXX add further sanity checks */
 
index 2f665a5..f50e88b 100644 (file)
@@ -235,14 +235,14 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
        else
                min_mtu -= 21;
 
-       if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= min_mtu) {
+       if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) {
                if (!(dst_metric_locked(dst, RTAX_MTU))) {
                        dst->metrics[RTAX_MTU-1] = mtu;
                        dst_set_expires(dst, dn_rt_mtu_expires);
                }
                if (!(dst_metric_locked(dst, RTAX_ADVMSS))) {
                        u32 mss = mtu - DN_MAX_NSP_DATA_HEADER;
-                       if (dst->metrics[RTAX_ADVMSS-1] > mss)
+                       if (dst_metric(dst, RTAX_ADVMSS) > mss)
                                dst->metrics[RTAX_ADVMSS-1] = mss;
                }
        }
@@ -805,12 +805,12 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
                rt->u.dst.neighbour = n;
        }
 
-       if (rt->u.dst.metrics[RTAX_MTU-1] == 0 ||
-           rt->u.dst.metrics[RTAX_MTU-1] > rt->u.dst.dev->mtu)
+       if (dst_metric(&rt->u.dst, RTAX_MTU) == 0 ||
+           dst_metric(&rt->u.dst, RTAX_MTU) > rt->u.dst.dev->mtu)
                rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
        mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->u.dst));
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0 ||
-           rt->u.dst.metrics[RTAX_ADVMSS-1] > mss)
+       if (dst_metric(&rt->u.dst, RTAX_ADVMSS) == 0 ||
+           dst_metric(&rt->u.dst, RTAX_ADVMSS) > mss)
                rt->u.dst.metrics[RTAX_ADVMSS-1] = mss;
        return 0;
 }
index 5e3685c..92f90ae 100644 (file)
@@ -1468,14 +1468,14 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
 
                                        /* BSD 4.2 compatibility hack :-( */
                                        if (mtu == 0 &&
-                                           old_mtu >= rth->u.dst.metrics[RTAX_MTU-1] &&
+                                           old_mtu >= dst_metric(&rth->u.dst, RTAX_MTU) &&
                                            old_mtu >= 68 + (iph->ihl << 2))
                                                old_mtu -= iph->ihl << 2;
 
                                        mtu = guess_mtu(old_mtu);
                                }
-                               if (mtu <= rth->u.dst.metrics[RTAX_MTU-1]) {
-                                       if (mtu < rth->u.dst.metrics[RTAX_MTU-1]) {
+                               if (mtu <= dst_metric(&rth->u.dst, RTAX_MTU)) {
+                                       if (mtu < dst_metric(&rth->u.dst, RTAX_MTU)) {
                                                dst_confirm(&rth->u.dst);
                                                if (mtu < ip_rt_min_pmtu) {
                                                        mtu = ip_rt_min_pmtu;
@@ -1497,7 +1497,7 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
 
 static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
-       if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= 68 &&
+       if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= 68 &&
            !(dst_metric_locked(dst, RTAX_MTU))) {
                if (mtu < ip_rt_min_pmtu) {
                        mtu = ip_rt_min_pmtu;
@@ -1613,7 +1613,7 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
                       sizeof(rt->u.dst.metrics));
                if (fi->fib_mtu == 0) {
                        rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
-                       if (rt->u.dst.metrics[RTAX_LOCK-1] & (1 << RTAX_MTU) &&
+                       if (dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
                            rt->rt_gateway != rt->rt_dst &&
                            rt->u.dst.dev->mtu > 576)
                                rt->u.dst.metrics[RTAX_MTU-1] = 576;
@@ -1624,14 +1624,14 @@ static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
        } else
                rt->u.dst.metrics[RTAX_MTU-1]= rt->u.dst.dev->mtu;
 
-       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0)
                rt->u.dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl;
-       if (rt->u.dst.metrics[RTAX_MTU-1] > IP_MAX_MTU)
+       if (dst_metric(&rt->u.dst, RTAX_MTU) > IP_MAX_MTU)
                rt->u.dst.metrics[RTAX_MTU-1] = IP_MAX_MTU;
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_ADVMSS) == 0)
                rt->u.dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->u.dst.dev->mtu - 40,
                                       ip_rt_min_advmss);
-       if (rt->u.dst.metrics[RTAX_ADVMSS-1] > 65535 - 40)
+       if (dst_metric(&rt->u.dst, RTAX_ADVMSS) > 65535 - 40)
                rt->u.dst.metrics[RTAX_ADVMSS-1] = 65535 - 40;
 
 #ifdef CONFIG_NET_CLS_ROUTE
index eda4f4a..8ac15a6 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/sysctl.h>
+#include <net/dst.h>
 #include <net/tcp.h>
 #include <net/inet_common.h>
 #include <linux/ipsec.h>
@@ -605,7 +606,7 @@ static u32 tcp_rto_min(struct sock *sk)
        u32 rto_min = TCP_RTO_MIN;
 
        if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
-               rto_min = dst->metrics[RTAX_RTO_MIN - 1];
+               rto_min = dst_metric(dst, RTAX_RTO_MIN);
        return rto_min;
 }
 
@@ -769,7 +770,7 @@ void tcp_update_metrics(struct sock *sk)
                                dst->metrics[RTAX_RTTVAR - 1] = m;
                        else
                                dst->metrics[RTAX_RTTVAR-1] -=
-                                       (dst->metrics[RTAX_RTTVAR-1] - m)>>2;
+                                       (dst_metric(dst, RTAX_RTTVAR) - m)>>2;
                }
 
                if (tp->snd_ssthresh >= 0xFFFF) {
@@ -788,21 +789,21 @@ void tcp_update_metrics(struct sock *sk)
                                dst->metrics[RTAX_SSTHRESH-1] =
                                        max(tp->snd_cwnd >> 1, tp->snd_ssthresh);
                        if (!dst_metric_locked(dst, RTAX_CWND))
-                               dst->metrics[RTAX_CWND-1] = (dst->metrics[RTAX_CWND-1] + tp->snd_cwnd) >> 1;
+                               dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_cwnd) >> 1;
                } else {
                        /* Else slow start did not finish, cwnd is non-sense,
                           ssthresh may be also invalid.
                         */
                        if (!dst_metric_locked(dst, RTAX_CWND))
-                               dst->metrics[RTAX_CWND-1] = (dst->metrics[RTAX_CWND-1] + tp->snd_ssthresh) >> 1;
-                       if (dst->metrics[RTAX_SSTHRESH-1] &&
+                               dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_ssthresh) >> 1;
+                       if (dst_metric(dst, RTAX_SSTHRESH) &&
                            !dst_metric_locked(dst, RTAX_SSTHRESH) &&
-                           tp->snd_ssthresh > dst->metrics[RTAX_SSTHRESH-1])
+                           tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH))
                                dst->metrics[RTAX_SSTHRESH-1] = tp->snd_ssthresh;
                }
 
                if (!dst_metric_locked(dst, RTAX_REORDERING)) {
-                       if (dst->metrics[RTAX_REORDERING-1] < tp->reordering &&
+                       if (dst_metric(dst, RTAX_REORDERING) < tp->reordering &&
                            tp->reordering != sysctl_tcp_reordering)
                                dst->metrics[RTAX_REORDERING-1] = tp->reordering;
                }
index a493ad9..12bba08 100644 (file)
@@ -1243,11 +1243,11 @@ install_route:
                }
        }
 
-       if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+       if (dst_metric(&rt->u.dst, RTAX_HOPLIMIT) == 0)
                rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
-       if (!rt->u.dst.metrics[RTAX_MTU-1])
+       if (!dst_metric(&rt->u.dst, RTAX_MTU))
                rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
-       if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
+       if (!dst_metric(&rt->u.dst, RTAX_ADVMSS))
                rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->u.dst));
        rt->u.dst.dev = dev;
        rt->rt6i_idev = idev;
index 9ad4e36..915afad 100644 (file)
@@ -1766,6 +1766,7 @@ fail_wep:
 fail_rate:
        ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
        unregister_netdevice(local->mdev);
+       local->mdev = NULL;
 fail_dev:
        rtnl_unlock();
        sta_info_stop(local);
@@ -1773,8 +1774,10 @@ fail_sta_info:
        debugfs_hw_del(local);
        destroy_workqueue(local->hw.workqueue);
 fail_workqueue:
-       ieee80211_if_free(local->mdev);
-       local->mdev = NULL;
+       if (local->mdev != NULL) {
+               ieee80211_if_free(local->mdev);
+               local->mdev = NULL;
+       }
 fail_mdev_alloc:
        wiphy_unregister(local->hw.wiphy);
        return result;
index 64b2d13..1d421d0 100644 (file)
@@ -6,7 +6,7 @@
  *             as published by the Free Software Foundation; either version
  *             2 of the License, or (at your option) any later version.
  *
- * Authors:    Jamal Hadi Salim (2005)
+ * Authors:    Jamal Hadi Salim (2005-8)
  *
  */
 
@@ -34,6 +34,7 @@ static struct tcf_hashinfo simp_hash_info = {
        .lock   =       &simp_lock,
 };
 
+#define SIMP_MAX_DATA  32
 static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result *res)
 {
        struct tcf_defact *d = a->priv;
@@ -69,23 +70,28 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
        return ret;
 }
 
-static int alloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
+static int alloc_defdata(struct tcf_defact *d, char *defdata)
 {
-       d->tcfd_defdata = kmemdup(defdata, datalen, GFP_KERNEL);
+       d->tcfd_defdata = kstrndup(defdata, SIMP_MAX_DATA, GFP_KERNEL);
        if (unlikely(!d->tcfd_defdata))
                return -ENOMEM;
-       d->tcfd_datalen = datalen;
+
        return 0;
 }
 
-static int realloc_defdata(struct tcf_defact *d, u32 datalen, void *defdata)
+static void reset_policy(struct tcf_defact *d, char *defdata,
+                        struct tc_defact *p)
 {
-       kfree(d->tcfd_defdata);
-       return alloc_defdata(d, datalen, defdata);
+       spin_lock_bh(&d->tcf_lock);
+       d->tcf_action = p->action;
+       memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
+       strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
+       spin_unlock_bh(&d->tcf_lock);
 }
 
 static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
        [TCA_DEF_PARMS] = { .len = sizeof(struct tc_defact) },
+       [TCA_DEF_DATA]  = { .type = NLA_STRING, .len = SIMP_MAX_DATA },
 };
 
 static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
@@ -95,28 +101,24 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
        struct tc_defact *parm;
        struct tcf_defact *d;
        struct tcf_common *pc;
-       void *defdata;
-       u32 datalen = 0;
+       char *defdata;
        int ret = 0, err;
 
        if (nla == NULL)
                return -EINVAL;
 
-       err = nla_parse_nested(tb, TCA_DEF_MAX, nla, NULL);
+       err = nla_parse_nested(tb, TCA_DEF_MAX, nla, simple_policy);
        if (err < 0)
                return err;
 
        if (tb[TCA_DEF_PARMS] == NULL)
                return -EINVAL;
 
-       parm = nla_data(tb[TCA_DEF_PARMS]);
-       defdata = nla_data(tb[TCA_DEF_DATA]);
-       if (defdata == NULL)
+       if (tb[TCA_DEF_DATA] == NULL)
                return -EINVAL;
 
-       datalen = nla_len(tb[TCA_DEF_DATA]);
-       if (datalen == 0)
-               return -EINVAL;
+       parm = nla_data(tb[TCA_DEF_PARMS]);
+       defdata = nla_data(tb[TCA_DEF_DATA]);
 
        pc = tcf_hash_check(parm->index, a, bind, &simp_hash_info);
        if (!pc) {
@@ -126,11 +128,12 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
                        return -ENOMEM;
 
                d = to_defact(pc);
-               ret = alloc_defdata(d, datalen, defdata);
+               ret = alloc_defdata(d, defdata);
                if (ret < 0) {
                        kfree(pc);
                        return ret;
                }
+               d->tcf_action = parm->action;
                ret = ACT_P_CREATED;
        } else {
                d = to_defact(pc);
@@ -138,13 +141,9 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est,
                        tcf_simp_release(d, bind);
                        return -EEXIST;
                }
-               realloc_defdata(d, datalen, defdata);
+               reset_policy(d, defdata, parm);
        }
 
-       spin_lock_bh(&d->tcf_lock);
-       d->tcf_action = parm->action;
-       spin_unlock_bh(&d->tcf_lock);
-
        if (ret == ACT_P_CREATED)
                tcf_hash_insert(pc, &simp_hash_info);
        return ret;
@@ -172,7 +171,7 @@ static inline int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
        opt.bindcnt = d->tcf_bindcnt - bind;
        opt.action = d->tcf_action;
        NLA_PUT(skb, TCA_DEF_PARMS, sizeof(opt), &opt);
-       NLA_PUT(skb, TCA_DEF_DATA, d->tcfd_datalen, d->tcfd_defdata);
+       NLA_PUT_STRING(skb, TCA_DEF_DATA, d->tcfd_defdata);
        t.install = jiffies_to_clock_t(jiffies - d->tcf_tm.install);
        t.lastuse = jiffies_to_clock_t(jiffies - d->tcf_tm.lastuse);
        t.expires = jiffies_to_clock_t(d->tcf_tm.expires);
index 66148cc..5bc1ed4 100644 (file)
@@ -1197,12 +1197,16 @@ static inline int htb_parent_last_child(struct htb_class *cl)
        return 1;
 }
 
-static void htb_parent_to_leaf(struct htb_class *cl, struct Qdisc *new_q)
+static void htb_parent_to_leaf(struct htb_sched *q, struct htb_class *cl,
+                              struct Qdisc *new_q)
 {
        struct htb_class *parent = cl->parent;
 
        BUG_TRAP(!cl->level && cl->un.leaf.q && !cl->prio_activity);
 
+       if (parent->cmode != HTB_CAN_SEND)
+               htb_safe_rb_erase(&parent->pq_node, q->wait_pq + parent->level);
+
        parent->level = 0;
        memset(&parent->un.inner, 0, sizeof(parent->un.inner));
        INIT_LIST_HEAD(&parent->un.leaf.drop_list);
@@ -1300,7 +1304,7 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg)
                htb_deactivate(q, cl);
 
        if (last_child)
-               htb_parent_to_leaf(cl, new_q);
+               htb_parent_to_leaf(q, cl, new_q);
 
        if (--cl->refcnt == 0)
                htb_destroy_class(sch, cl);