@@ -390,6 +390,7 @@ static struct tcf_proto *tcf_proto_create(const char *kind, u32 protocol,
390390 tp -> protocol = protocol ;
391391 tp -> prio = prio ;
392392 tp -> chain = chain ;
393+ tp -> usesw = !tp -> ops -> reoffload ;
393394 spin_lock_init (& tp -> lock );
394395 refcount_set (& tp -> refcnt , 1 );
395396
@@ -410,39 +411,31 @@ static void tcf_proto_get(struct tcf_proto *tp)
410411 refcount_inc (& tp -> refcnt );
411412}
412413
413- static void tcf_maintain_bypass (struct tcf_block * block )
414+ static void tcf_proto_count_usesw (struct tcf_proto * tp , bool add )
414415{
415- int filtercnt = atomic_read (& block -> filtercnt );
416- int skipswcnt = atomic_read (& block -> skipswcnt );
417- bool bypass_wanted = filtercnt > 0 && filtercnt == skipswcnt ;
418-
419- if (bypass_wanted != block -> bypass_wanted ) {
420416#ifdef CONFIG_NET_CLS_ACT
421- if (bypass_wanted )
422- static_branch_inc (& tcf_bypass_check_needed_key );
423- else
424- static_branch_dec (& tcf_bypass_check_needed_key );
425- #endif
426- block -> bypass_wanted = bypass_wanted ;
417+ struct tcf_block * block = tp -> chain -> block ;
418+ bool counted = false;
419+
420+ if (!add ) {
421+ if (tp -> usesw && tp -> counted ) {
422+ if (!atomic_dec_return (& block -> useswcnt ))
423+ static_branch_dec (& tcf_sw_enabled_key );
424+ tp -> counted = false;
425+ }
426+ return ;
427427 }
428- }
429-
430- static void tcf_block_filter_cnt_update (struct tcf_block * block , bool * counted , bool add )
431- {
432- lockdep_assert_not_held (& block -> cb_lock );
433428
434- down_write (& block -> cb_lock );
435- if (* counted != add ) {
436- if (add ) {
437- atomic_inc (& block -> filtercnt );
438- * counted = true;
439- } else {
440- atomic_dec (& block -> filtercnt );
441- * counted = false;
442- }
429+ spin_lock (& tp -> lock );
430+ if (tp -> usesw && !tp -> counted ) {
431+ counted = true;
432+ tp -> counted = true;
443433 }
444- tcf_maintain_bypass (block );
445- up_write (& block -> cb_lock );
434+ spin_unlock (& tp -> lock );
435+
436+ if (counted && atomic_inc_return (& block -> useswcnt ) == 1 )
437+ static_branch_inc (& tcf_sw_enabled_key );
438+ #endif
446439}
447440
448441static void tcf_chain_put (struct tcf_chain * chain );
@@ -451,7 +444,7 @@ static void tcf_proto_destroy(struct tcf_proto *tp, bool rtnl_held,
451444 bool sig_destroy , struct netlink_ext_ack * extack )
452445{
453446 tp -> ops -> destroy (tp , rtnl_held , extack );
454- tcf_block_filter_cnt_update (tp -> chain -> block , & tp -> counted , false);
447+ tcf_proto_count_usesw (tp , false);
455448 if (sig_destroy )
456449 tcf_proto_signal_destroyed (tp -> chain , tp );
457450 tcf_chain_put (tp -> chain );
@@ -2404,7 +2397,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
24042397 tfilter_notify (net , skb , n , tp , block , q , parent , fh ,
24052398 RTM_NEWTFILTER , false, rtnl_held , extack );
24062399 tfilter_put (tp , fh );
2407- tcf_block_filter_cnt_update ( block , & tp -> counted , true);
2400+ tcf_proto_count_usesw ( tp , true);
24082401 /* q pointer is NULL for shared blocks */
24092402 if (q )
24102403 q -> flags &= ~TCQ_F_CAN_BYPASS ;
@@ -3521,8 +3514,6 @@ static void tcf_block_offload_inc(struct tcf_block *block, u32 *flags)
35213514 if (* flags & TCA_CLS_FLAGS_IN_HW )
35223515 return ;
35233516 * flags |= TCA_CLS_FLAGS_IN_HW ;
3524- if (tc_skip_sw (* flags ))
3525- atomic_inc (& block -> skipswcnt );
35263517 atomic_inc (& block -> offloadcnt );
35273518}
35283519
@@ -3531,8 +3522,6 @@ static void tcf_block_offload_dec(struct tcf_block *block, u32 *flags)
35313522 if (!(* flags & TCA_CLS_FLAGS_IN_HW ))
35323523 return ;
35333524 * flags &= ~TCA_CLS_FLAGS_IN_HW ;
3534- if (tc_skip_sw (* flags ))
3535- atomic_dec (& block -> skipswcnt );
35363525 atomic_dec (& block -> offloadcnt );
35373526}
35383527
0 commit comments