@@ -623,9 +623,50 @@ mlxsw_sp_acl_erp_region_ctcam_disable(struct mlxsw_sp_acl_erp_table *erp_table)
623623 mlxsw_sp_acl_erp_table_enable (erp_table , false);
624624}
625625
626+ static int
627+ __mlxsw_sp_acl_erp_table_other_inc (struct mlxsw_sp_acl_erp_table * erp_table ,
628+ unsigned int * inc_num )
629+ {
630+ int err ;
631+
632+ /* If there are C-TCAM eRPs in use we need to transition
633+ * the region to use eRP table, if it is not already done
634+ */
635+ if (erp_table -> ops != & erp_two_masks_ops &&
636+ erp_table -> ops != & erp_multiple_masks_ops ) {
637+ err = mlxsw_sp_acl_erp_region_table_trans (erp_table );
638+ if (err )
639+ return err ;
640+ }
641+
642+ /* When C-TCAM is used, the eRP table must be used */
643+ if (erp_table -> ops != & erp_multiple_masks_ops )
644+ erp_table -> ops = & erp_multiple_masks_ops ;
645+
646+ (* inc_num )++ ;
647+
648+ return 0 ;
649+ }
650+
651+ static int mlxsw_sp_acl_erp_ctcam_inc (struct mlxsw_sp_acl_erp_table * erp_table )
652+ {
653+ return __mlxsw_sp_acl_erp_table_other_inc (erp_table ,
654+ & erp_table -> num_ctcam_erps );
655+ }
656+
626657static void
627- mlxsw_sp_acl_erp_ctcam_table_ops_set (struct mlxsw_sp_acl_erp_table * erp_table )
658+ __mlxsw_sp_acl_erp_table_other_dec (struct mlxsw_sp_acl_erp_table * erp_table ,
659+ unsigned int * dec_num )
628660{
661+ (* dec_num )-- ;
662+
663+ /* If there are no C-TCAM eRPs in use, the state we
664+ * transition to depends on the number of A-TCAM eRPs currently
665+ * in use.
666+ */
667+ if (erp_table -> num_ctcam_erps > 0 )
668+ return ;
669+
629670 switch (erp_table -> num_atcam_erps ) {
630671 case 2 :
631672 /* Keep using the eRP table, but correctly set the
@@ -659,9 +700,15 @@ mlxsw_sp_acl_erp_ctcam_table_ops_set(struct mlxsw_sp_acl_erp_table *erp_table)
659700 }
660701}
661702
703+ static void mlxsw_sp_acl_erp_ctcam_dec (struct mlxsw_sp_acl_erp_table * erp_table )
704+ {
705+ __mlxsw_sp_acl_erp_table_other_dec (erp_table ,
706+ & erp_table -> num_ctcam_erps );
707+ }
708+
662709static struct mlxsw_sp_acl_erp *
663- __mlxsw_sp_acl_erp_ctcam_mask_create (struct mlxsw_sp_acl_erp_table * erp_table ,
664- struct mlxsw_sp_acl_erp_key * key )
710+ mlxsw_sp_acl_erp_ctcam_mask_create (struct mlxsw_sp_acl_erp_table * erp_table ,
711+ struct mlxsw_sp_acl_erp_key * key )
665712{
666713 struct mlxsw_sp_acl_erp * erp ;
667714 int err ;
@@ -673,7 +720,11 @@ __mlxsw_sp_acl_erp_ctcam_mask_create(struct mlxsw_sp_acl_erp_table *erp_table,
673720 memcpy (& erp -> key , key , sizeof (* key ));
674721 bitmap_from_arr32 (erp -> mask_bitmap , (u32 * ) key -> mask ,
675722 MLXSW_SP_ACL_TCAM_MASK_LEN );
676- erp_table -> num_ctcam_erps ++ ;
723+
724+ err = mlxsw_sp_acl_erp_ctcam_inc (erp_table );
725+ if (err )
726+ goto err_erp_ctcam_inc ;
727+
677728 erp -> erp_table = erp_table ;
678729
679730 err = mlxsw_sp_acl_erp_master_mask_set (erp_table , & erp -> key );
@@ -684,67 +735,26 @@ __mlxsw_sp_acl_erp_ctcam_mask_create(struct mlxsw_sp_acl_erp_table *erp_table,
684735 if (err )
685736 goto err_erp_region_ctcam_enable ;
686737
687- /* When C-TCAM is used, the eRP table must be used */
688- erp_table -> ops = & erp_multiple_masks_ops ;
689-
690738 return erp ;
691739
692740err_erp_region_ctcam_enable :
693741 mlxsw_sp_acl_erp_master_mask_clear (erp_table , & erp -> key );
694742err_master_mask_set :
695- erp_table -> num_ctcam_erps -- ;
743+ mlxsw_sp_acl_erp_ctcam_dec (erp_table );
744+ err_erp_ctcam_inc :
696745 kfree (erp );
697746 return ERR_PTR (err );
698747}
699748
700- static struct mlxsw_sp_acl_erp *
701- mlxsw_sp_acl_erp_ctcam_mask_create (struct mlxsw_sp_acl_erp_table * erp_table ,
702- struct mlxsw_sp_acl_erp_key * key )
703- {
704- struct mlxsw_sp_acl_erp * erp ;
705- int err ;
706-
707- /* There is a special situation where we need to spill rules
708- * into the C-TCAM, yet the region is still using a master
709- * mask and thus not performing a lookup in the C-TCAM. This
710- * can happen when two rules that only differ in priority - and
711- * thus sharing the same key - are programmed. In this case
712- * we transition the region to use an eRP table
713- */
714- err = mlxsw_sp_acl_erp_region_table_trans (erp_table );
715- if (err )
716- return ERR_PTR (err );
717-
718- erp = __mlxsw_sp_acl_erp_ctcam_mask_create (erp_table , key );
719- if (IS_ERR (erp )) {
720- err = PTR_ERR (erp );
721- goto err_erp_create ;
722- }
723-
724- return erp ;
725-
726- err_erp_create :
727- mlxsw_sp_acl_erp_region_master_mask_trans (erp_table );
728- return ERR_PTR (err );
729- }
730-
731749static void
732750mlxsw_sp_acl_erp_ctcam_mask_destroy (struct mlxsw_sp_acl_erp * erp )
733751{
734752 struct mlxsw_sp_acl_erp_table * erp_table = erp -> erp_table ;
735753
736754 mlxsw_sp_acl_erp_region_ctcam_disable (erp_table );
737755 mlxsw_sp_acl_erp_master_mask_clear (erp_table , & erp -> key );
738- erp_table -> num_ctcam_erps -- ;
756+ mlxsw_sp_acl_erp_ctcam_dec ( erp_table ) ;
739757 kfree (erp );
740-
741- /* Once the last C-TCAM eRP was destroyed, the state we
742- * transition to depends on the number of A-TCAM eRPs currently
743- * in use
744- */
745- if (erp_table -> num_ctcam_erps > 0 )
746- return ;
747- mlxsw_sp_acl_erp_ctcam_table_ops_set (erp_table );
748758}
749759
750760static struct mlxsw_sp_acl_erp *
@@ -755,7 +765,7 @@ mlxsw_sp_acl_erp_mask_create(struct mlxsw_sp_acl_erp_table *erp_table,
755765 int err ;
756766
757767 if (key -> ctcam )
758- return __mlxsw_sp_acl_erp_ctcam_mask_create (erp_table , key );
768+ return mlxsw_sp_acl_erp_ctcam_mask_create (erp_table , key );
759769
760770 /* Expand the eRP table for the new eRP, if needed */
761771 err = mlxsw_sp_acl_erp_table_expand (erp_table );
0 commit comments