1010#include <linux/netdevice.h>
1111#include <linux/mutex.h>
1212#include <linux/refcount.h>
13+ #include <linux/idr.h>
1314#include <net/devlink.h>
1415#include <trace/events/mlxsw.h>
1516
@@ -58,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
5859static int mlxsw_sp_acl_tcam_region_id_get (struct mlxsw_sp_acl_tcam * tcam ,
5960 u16 * p_id )
6061{
61- u16 id ;
62+ int id ;
6263
63- id = find_first_zero_bit (tcam -> used_regions , tcam -> max_regions );
64- if (id < tcam -> max_regions ) {
65- __set_bit (id , tcam -> used_regions );
66- * p_id = id ;
67- return 0 ;
68- }
69- return - ENOBUFS ;
64+ id = ida_alloc_max (& tcam -> used_regions , tcam -> max_regions - 1 ,
65+ GFP_KERNEL );
66+ if (id < 0 )
67+ return id ;
68+
69+ * p_id = id ;
70+
71+ return 0 ;
7072}
7173
7274static void mlxsw_sp_acl_tcam_region_id_put (struct mlxsw_sp_acl_tcam * tcam ,
7375 u16 id )
7476{
75- __clear_bit ( id , tcam -> used_regions );
77+ ida_free ( & tcam -> used_regions , id );
7678}
7779
7880static int mlxsw_sp_acl_tcam_group_id_get (struct mlxsw_sp_acl_tcam * tcam ,
7981 u16 * p_id )
8082{
81- u16 id ;
83+ int id ;
8284
83- id = find_first_zero_bit (tcam -> used_groups , tcam -> max_groups );
84- if (id < tcam -> max_groups ) {
85- __set_bit (id , tcam -> used_groups );
86- * p_id = id ;
87- return 0 ;
88- }
89- return - ENOBUFS ;
85+ id = ida_alloc_max (& tcam -> used_groups , tcam -> max_groups - 1 ,
86+ GFP_KERNEL );
87+ if (id < 0 )
88+ return id ;
89+
90+ * p_id = id ;
91+
92+ return 0 ;
9093}
9194
9295static void mlxsw_sp_acl_tcam_group_id_put (struct mlxsw_sp_acl_tcam * tcam ,
9396 u16 id )
9497{
95- __clear_bit ( id , tcam -> used_groups );
98+ ida_free ( & tcam -> used_groups , id );
9699}
97100
98101struct mlxsw_sp_acl_tcam_pattern {
@@ -715,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
715718 rehash .dw .work );
716719 int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS ;
717720
721+ mutex_lock (& vregion -> lock );
718722 mlxsw_sp_acl_tcam_vregion_rehash (vregion -> mlxsw_sp , vregion , & credits );
723+ mutex_unlock (& vregion -> lock );
719724 if (credits < 0 )
720725 /* Rehash gone out of credits so it was interrupted.
721726 * Schedule the work as soon as possible to continue.
@@ -725,6 +730,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
725730 mlxsw_sp_acl_tcam_vregion_rehash_work_schedule (vregion );
726731}
727732
733+ static void
734+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset (struct mlxsw_sp_acl_tcam_rehash_ctx * ctx )
735+ {
736+ /* The entry markers are relative to the current chunk and therefore
737+ * needs to be reset together with the chunk marker.
738+ */
739+ ctx -> current_vchunk = NULL ;
740+ ctx -> start_ventry = NULL ;
741+ ctx -> stop_ventry = NULL ;
742+ }
743+
728744static void
729745mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed (struct mlxsw_sp_acl_tcam_vchunk * vchunk )
730746{
@@ -747,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v
747763 * the current chunk pointer to make sure all chunks
748764 * are properly migrated.
749765 */
750- vregion -> rehash .ctx . current_vchunk = NULL ;
766+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset ( & vregion -> rehash .ctx ) ;
751767}
752768
753769static struct mlxsw_sp_acl_tcam_vregion *
@@ -820,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
820836 struct mlxsw_sp_acl_tcam * tcam = vregion -> tcam ;
821837
822838 if (vgroup -> vregion_rehash_enabled && ops -> region_rehash_hints_get ) {
839+ struct mlxsw_sp_acl_tcam_rehash_ctx * ctx = & vregion -> rehash .ctx ;
840+
823841 mutex_lock (& tcam -> lock );
824842 list_del (& vregion -> tlist );
825843 mutex_unlock (& tcam -> lock );
826- cancel_delayed_work_sync (& vregion -> rehash .dw );
844+ if (cancel_delayed_work_sync (& vregion -> rehash .dw ) &&
845+ ctx -> hints_priv )
846+ ops -> region_rehash_hints_put (ctx -> hints_priv );
827847 }
828848 mlxsw_sp_acl_tcam_vgroup_vregion_detach (mlxsw_sp , vregion );
829849 if (vregion -> region2 )
@@ -1154,8 +1174,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
11541174 struct mlxsw_sp_acl_tcam_ventry * ventry ,
11551175 bool * activity )
11561176{
1157- return mlxsw_sp_acl_tcam_entry_activity_get (mlxsw_sp ,
1158- ventry -> entry , activity );
1177+ struct mlxsw_sp_acl_tcam_vregion * vregion = ventry -> vchunk -> vregion ;
1178+ int err ;
1179+
1180+ mutex_lock (& vregion -> lock );
1181+ err = mlxsw_sp_acl_tcam_entry_activity_get (mlxsw_sp , ventry -> entry ,
1182+ activity );
1183+ mutex_unlock (& vregion -> lock );
1184+ return err ;
11591185}
11601186
11611187static int
@@ -1189,6 +1215,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
11891215{
11901216 struct mlxsw_sp_acl_tcam_chunk * new_chunk ;
11911217
1218+ WARN_ON (vchunk -> chunk2 );
1219+
11921220 new_chunk = mlxsw_sp_acl_tcam_chunk_create (mlxsw_sp , vchunk , region );
11931221 if (IS_ERR (new_chunk ))
11941222 return PTR_ERR (new_chunk );
@@ -1207,7 +1235,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
12071235{
12081236 mlxsw_sp_acl_tcam_chunk_destroy (mlxsw_sp , vchunk -> chunk2 );
12091237 vchunk -> chunk2 = NULL ;
1210- ctx -> current_vchunk = NULL ;
1238+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset ( ctx ) ;
12111239}
12121240
12131241static int
@@ -1230,6 +1258,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
12301258 return 0 ;
12311259 }
12321260
1261+ if (list_empty (& vchunk -> ventry_list ))
1262+ goto out ;
1263+
12331264 /* If the migration got interrupted, we have the ventry to start from
12341265 * stored in context.
12351266 */
@@ -1239,6 +1270,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
12391270 ventry = list_first_entry (& vchunk -> ventry_list ,
12401271 typeof (* ventry ), list );
12411272
1273+ WARN_ON (ventry -> vchunk != vchunk );
1274+
12421275 list_for_each_entry_from (ventry , & vchunk -> ventry_list , list ) {
12431276 /* During rollback, once we reach the ventry that failed
12441277 * to migrate, we are done.
@@ -1279,6 +1312,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
12791312 }
12801313 }
12811314
1315+ out :
12821316 mlxsw_sp_acl_tcam_vchunk_migrate_end (mlxsw_sp , vchunk , ctx );
12831317 return 0 ;
12841318}
@@ -1292,6 +1326,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
12921326 struct mlxsw_sp_acl_tcam_vchunk * vchunk ;
12931327 int err ;
12941328
1329+ if (list_empty (& vregion -> vchunk_list ))
1330+ return 0 ;
1331+
12951332 /* If the migration got interrupted, we have the vchunk
12961333 * we are working on stored in context.
12971334 */
@@ -1320,16 +1357,17 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
13201357 int err , err2 ;
13211358
13221359 trace_mlxsw_sp_acl_tcam_vregion_migrate (mlxsw_sp , vregion );
1323- mutex_lock (& vregion -> lock );
13241360 err = mlxsw_sp_acl_tcam_vchunk_migrate_all (mlxsw_sp , vregion ,
13251361 ctx , credits );
13261362 if (err ) {
1363+ if (ctx -> this_is_rollback )
1364+ return err ;
13271365 /* In case migration was not successful, we need to swap
13281366 * so the original region pointer is assigned again
13291367 * to vregion->region.
13301368 */
13311369 swap (vregion -> region , vregion -> region2 );
1332- ctx -> current_vchunk = NULL ;
1370+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset ( ctx ) ;
13331371 ctx -> this_is_rollback = true;
13341372 err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all (mlxsw_sp , vregion ,
13351373 ctx , credits );
@@ -1340,7 +1378,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
13401378 /* Let the rollback to be continued later on. */
13411379 }
13421380 }
1343- mutex_unlock (& vregion -> lock );
13441381 trace_mlxsw_sp_acl_tcam_vregion_migrate_end (mlxsw_sp , vregion );
13451382 return err ;
13461383}
@@ -1389,6 +1426,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
13891426
13901427 ctx -> hints_priv = hints_priv ;
13911428 ctx -> this_is_rollback = false;
1429+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset (ctx );
13921430
13931431 return 0 ;
13941432
@@ -1441,7 +1479,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
14411479 err = mlxsw_sp_acl_tcam_vregion_migrate (mlxsw_sp , vregion ,
14421480 ctx , credits );
14431481 if (err ) {
1444- dev_err (mlxsw_sp -> bus_info -> dev , "Failed to migrate vregion\n" );
1482+ dev_err_ratelimited (mlxsw_sp -> bus_info -> dev , "Failed to migrate vregion\n" );
1483+ return ;
14451484 }
14461485
14471486 if (* credits >= 0 )
@@ -1549,19 +1588,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
15491588 if (max_tcam_regions < max_regions )
15501589 max_regions = max_tcam_regions ;
15511590
1552- tcam -> used_regions = bitmap_zalloc (max_regions , GFP_KERNEL );
1553- if (!tcam -> used_regions ) {
1554- err = - ENOMEM ;
1555- goto err_alloc_used_regions ;
1556- }
1591+ ida_init (& tcam -> used_regions );
15571592 tcam -> max_regions = max_regions ;
15581593
15591594 max_groups = MLXSW_CORE_RES_GET (mlxsw_sp -> core , ACL_MAX_GROUPS );
1560- tcam -> used_groups = bitmap_zalloc (max_groups , GFP_KERNEL );
1561- if (!tcam -> used_groups ) {
1562- err = - ENOMEM ;
1563- goto err_alloc_used_groups ;
1564- }
1595+ ida_init (& tcam -> used_groups );
15651596 tcam -> max_groups = max_groups ;
15661597 tcam -> max_group_size = MLXSW_CORE_RES_GET (mlxsw_sp -> core ,
15671598 ACL_MAX_GROUP_SIZE );
@@ -1575,10 +1606,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
15751606 return 0 ;
15761607
15771608err_tcam_init :
1578- bitmap_free (tcam -> used_groups );
1579- err_alloc_used_groups :
1580- bitmap_free (tcam -> used_regions );
1581- err_alloc_used_regions :
1609+ ida_destroy (& tcam -> used_groups );
1610+ ida_destroy (& tcam -> used_regions );
15821611 mlxsw_sp_acl_tcam_rehash_params_unregister (mlxsw_sp );
15831612err_rehash_params_register :
15841613 mutex_destroy (& tcam -> lock );
@@ -1591,8 +1620,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
15911620 const struct mlxsw_sp_acl_tcam_ops * ops = mlxsw_sp -> acl_tcam_ops ;
15921621
15931622 ops -> fini (mlxsw_sp , tcam -> priv );
1594- bitmap_free ( tcam -> used_groups );
1595- bitmap_free ( tcam -> used_regions );
1623+ ida_destroy ( & tcam -> used_groups );
1624+ ida_destroy ( & tcam -> used_regions );
15961625 mlxsw_sp_acl_tcam_rehash_params_unregister (mlxsw_sp );
15971626 mutex_destroy (& tcam -> lock );
15981627}
0 commit comments