diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-01 20:09:08 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-12-01 20:09:08 -0800 |
commit | 5983fe2b29df5885880d7fa3b91aca306c7564ef (patch) | |
tree | c9d968a776b7d1f8dc446d2857f6cefddec6edb0 /net/sched/sch_teql.c | |
parent | 5611cc4572e889b62a7b4c72a413536bf6a9c416 (diff) | |
parent | 3ced1be5490f5c415d51a1e5918beeb9239d546b (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (73 commits)
netfilter: Remove ADVANCED dependency from NF_CONNTRACK_NETBIOS_NS
ipv4: flush route cache after change accept_local
sch_red: fix red_change
Revert "udp: remove redundant variable"
bridge: master device stuck in no-carrier state forever when in user-stp mode
ipv4: Perform peer validation on cached route lookup.
net/core: fix rollback handler in register_netdevice_notifier
sch_red: fix red_calc_qavg_from_idle_time
bonding: only use primary address for ARP
ipv4: fix lockdep splat in rt_cache_seq_show
sch_teql: fix lockdep splat
net: fec: Select the FEC driver by default for i.MX SoCs
isdn: avoid copying too long drvid
isdn: make sure strings are null terminated
netlabel: Fix build problems when IPv6 is not enabled
sctp: better integer overflow check in sctp_auth_create_key()
sctp: integer overflow in sctp_auth_create_key()
ipv6: Set mcast_hops to IPV6_DEFAULT_MCASTHOPS when -1 was given.
net: Fix corruption in /proc/*/net/dev_mcast
mac80211: fix race between the AGG SM and the Tx data path
...
Diffstat (limited to 'net/sched/sch_teql.c')
-rw-r--r-- | net/sched/sch_teql.c | 31 |
1 files changed, 20 insertions, 11 deletions
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index a3b7120fcc74..4f4c52c0eeb3 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -225,11 +225,11 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt) static int -__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev) +__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, + struct net_device *dev, struct netdev_queue *txq, + struct neighbour *mn) { - struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0); - struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc); - struct neighbour *mn = dst_get_neighbour(skb_dst(skb)); + struct teql_sched_data *q = qdisc_priv(txq->qdisc); struct neighbour *n = q->ncache; if (mn->tbl == NULL) @@ -262,17 +262,26 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device * } static inline int teql_resolve(struct sk_buff *skb, - struct sk_buff *skb_res, struct net_device *dev) + struct sk_buff *skb_res, + struct net_device *dev, + struct netdev_queue *txq) { - struct netdev_queue *txq = netdev_get_tx_queue(dev, 0); + struct dst_entry *dst = skb_dst(skb); + struct neighbour *mn; + int res; + if (txq->qdisc == &noop_qdisc) return -ENODEV; - if (dev->header_ops == NULL || - skb_dst(skb) == NULL || - dst_get_neighbour(skb_dst(skb)) == NULL) + if (!dev->header_ops || !dst) return 0; - return __teql_resolve(skb, skb_res, dev); + + rcu_read_lock(); + mn = dst_get_neighbour(dst); + res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0; + rcu_read_unlock(); + + return res; } static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) @@ -307,7 +316,7 @@ restart: continue; } - switch (teql_resolve(skb, skb_res, slave)) { + switch (teql_resolve(skb, skb_res, slave, slave_txq)) { case 0: if (__netif_tx_trylock(slave_txq)) { unsigned int length = qdisc_pkt_len(skb); |