aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_u32.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_u32.c')
-rw-r--r--net/sched/cls_u32.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 6c7601a530e3..ed8b6a24b9e9 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -96,7 +96,7 @@ struct tc_u_hnode {
96 96
97struct tc_u_common { 97struct tc_u_common {
98 struct tc_u_hnode __rcu *hlist; 98 struct tc_u_hnode __rcu *hlist;
99 struct tcf_block *block; 99 void *ptr;
100 int refcnt; 100 int refcnt;
101 struct idr handle_idr; 101 struct idr handle_idr;
102 struct hlist_node hnode; 102 struct hlist_node hnode;
@@ -330,9 +330,25 @@ static struct hlist_head *tc_u_common_hash;
330#define U32_HASH_SHIFT 10 330#define U32_HASH_SHIFT 10
331#define U32_HASH_SIZE (1 << U32_HASH_SHIFT) 331#define U32_HASH_SIZE (1 << U32_HASH_SHIFT)
332 332
333static void *tc_u_common_ptr(const struct tcf_proto *tp)
334{
335 struct tcf_block *block = tp->chain->block;
336
337 /* The block sharing is currently supported only
338 * for classless qdiscs. In that case we use block
339 * for tc_u_common identification. In case the
340 * block is not shared, block->q is a valid pointer
341 * and we can use that. That works for classful qdiscs.
342 */
343 if (tcf_block_shared(block))
344 return block;
345 else
346 return block->q;
347}
348
333static unsigned int tc_u_hash(const struct tcf_proto *tp) 349static unsigned int tc_u_hash(const struct tcf_proto *tp)
334{ 350{
335 return hash_ptr(tp->chain->block, U32_HASH_SHIFT); 351 return hash_ptr(tc_u_common_ptr(tp), U32_HASH_SHIFT);
336} 352}
337 353
338static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp) 354static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
@@ -342,7 +358,7 @@ static struct tc_u_common *tc_u_common_find(const struct tcf_proto *tp)
342 358
343 h = tc_u_hash(tp); 359 h = tc_u_hash(tp);
344 hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) { 360 hlist_for_each_entry(tc, &tc_u_common_hash[h], hnode) {
345 if (tc->block == tp->chain->block) 361 if (tc->ptr == tc_u_common_ptr(tp))
346 return tc; 362 return tc;
347 } 363 }
348 return NULL; 364 return NULL;
@@ -371,7 +387,7 @@ static int u32_init(struct tcf_proto *tp)
371 kfree(root_ht); 387 kfree(root_ht);
372 return -ENOBUFS; 388 return -ENOBUFS;
373 } 389 }
374 tp_c->block = tp->chain->block; 390 tp_c->ptr = tc_u_common_ptr(tp);
375 INIT_HLIST_NODE(&tp_c->hnode); 391 INIT_HLIST_NODE(&tp_c->hnode);
376 idr_init(&tp_c->handle_idr); 392 idr_init(&tp_c->handle_idr);
377 393