Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 256268
b: refs/heads/master
c: 5c25f68
h: refs/heads/master
v: v3
  • Loading branch information
David S. Miller committed Jul 13, 2011
1 parent d018122 commit 40ae48b
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e69dd336ee3a05a589629b505b18ba5e7a5b4c54
refs/heads/master: 5c25f686db352082eef8daa21b760192351a023a
9 changes: 2 additions & 7 deletions trunk/include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,20 +252,15 @@ struct netdev_hw_addr_list {
netdev_hw_addr_list_for_each(ha, &(dev)->mc)

struct hh_cache {
struct hh_cache *hh_next; /* Next entry */
atomic_t hh_refcnt; /* number of users */
/*
* We want hh_output, hh_len, hh_lock and hh_data be a in a separate
* cache line on SMP.
* They are mostly read, but hh_refcnt may be changed quite frequently,
* incurring cache line ping pongs.
*/
__be16 hh_type ____cacheline_aligned_in_smp;
/* protocol identifier, f.e ETH_P_IP
* NOTE: For VLANs, this will be the
* encapuslated type. --BLG
*/
u16 hh_len; /* length of header */
u16 hh_len ____cacheline_aligned_in_smp;
u16 __pad;
int (*hh_output)(struct sk_buff *skb);
seqlock_t hh_lock;

Expand Down
37 changes: 18 additions & 19 deletions trunk/net/core/neighbour.c
Original file line number Diff line number Diff line change
Expand Up @@ -702,9 +702,9 @@ void neigh_destroy(struct neighbour *neigh)
if (neigh_del_timer(neigh))
printk(KERN_WARNING "Impossible event.\n");

while ((hh = neigh->hh) != NULL) {
neigh->hh = hh->hh_next;
hh->hh_next = NULL;
hh = neigh->hh;
if (hh) {
neigh->hh = NULL;

write_seqlock_bh(&hh->hh_lock);
hh->hh_output = neigh_blackhole;
Expand Down Expand Up @@ -737,7 +737,8 @@ static void neigh_suspect(struct neighbour *neigh)

neigh->output = neigh->ops->output;

for (hh = neigh->hh; hh; hh = hh->hh_next)
hh = neigh->hh;
if (hh)
hh->hh_output = neigh->ops->output;
}

Expand All @@ -754,7 +755,8 @@ static void neigh_connect(struct neighbour *neigh)

neigh->output = neigh->ops->connected_output;

for (hh = neigh->hh; hh; hh = hh->hh_next)
hh = neigh->hh;
if (hh)
hh->hh_output = neigh->ops->hh_output;
}

Expand Down Expand Up @@ -1025,7 +1027,8 @@ static void neigh_update_hhs(const struct neighbour *neigh)
update = neigh->dev->header_ops->cache_update;

if (update) {
for (hh = neigh->hh; hh; hh = hh->hh_next) {
hh = neigh->hh;
if (hh) {
write_seqlock_bh(&hh->hh_lock);
update(hh, neigh->dev, neigh->ha);
write_sequnlock_bh(&hh->hh_lock);
Expand Down Expand Up @@ -1211,19 +1214,17 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
}
EXPORT_SYMBOL(neigh_event_ns);

static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst,
__be16 protocol)
static inline bool neigh_hh_lookup(struct neighbour *n, struct dst_entry *dst)
{
struct hh_cache *hh;

smp_rmb(); /* paired with smp_wmb() in neigh_hh_init() */
for (hh = n->hh; hh; hh = hh->hh_next) {
if (hh->hh_type == protocol) {
atomic_inc(&hh->hh_refcnt);
if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
hh_cache_put(hh);
return true;
}
hh = n->hh;
if (hh) {
atomic_inc(&hh->hh_refcnt);
if (unlikely(cmpxchg(&dst->hh, NULL, hh) != NULL))
hh_cache_put(hh);
return true;
}
return false;
}
Expand All @@ -1235,7 +1236,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
struct hh_cache *hh;
struct net_device *dev = dst->dev;

if (likely(neigh_hh_lookup(n, dst, protocol)))
if (likely(neigh_hh_lookup(n, dst)))
return;

/* slow path */
Expand All @@ -1244,7 +1245,6 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
return;

seqlock_init(&hh->hh_lock);
hh->hh_type = protocol;
atomic_set(&hh->hh_refcnt, 2);

if (dev->header_ops->cache(n, hh, protocol)) {
Expand All @@ -1255,7 +1255,7 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
write_lock_bh(&n->lock);

/* must check if another thread already did the insert */
if (neigh_hh_lookup(n, dst, protocol)) {
if (neigh_hh_lookup(n, dst)) {
kfree(hh);
goto end;
}
Expand All @@ -1265,7 +1265,6 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
else
hh->hh_output = n->ops->output;

hh->hh_next = n->hh;
smp_wmb(); /* paired with smp_rmb() in neigh_hh_lookup() */
n->hh = hh;

Expand Down

0 comments on commit 40ae48b

Please sign in to comment.