@@ -27,6 +27,7 @@ size_t mlxsw_sp_acl_tcam_priv_size(struct mlxsw_sp *mlxsw_sp)
2727
2828#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_DFLT 5000 /* ms */
2929#define MLXSW_SP_ACL_TCAM_VREGION_REHASH_INTRVL_MIN 3000 /* ms */
30+ #define MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS 100 /* number of entries */
3031
3132int mlxsw_sp_acl_tcam_init (struct mlxsw_sp * mlxsw_sp ,
3233 struct mlxsw_sp_acl_tcam * tcam )
@@ -732,16 +733,26 @@ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(struct mlxsw_sp_acl_tcam_vregion
732733
733734static int
734735mlxsw_sp_acl_tcam_vregion_rehash (struct mlxsw_sp * mlxsw_sp ,
735- struct mlxsw_sp_acl_tcam_vregion * vregion );
736+ struct mlxsw_sp_acl_tcam_vregion * vregion ,
737+ int * credits );
736738
737739static void mlxsw_sp_acl_tcam_vregion_rehash_work (struct work_struct * work )
738740{
739741 struct mlxsw_sp_acl_tcam_vregion * vregion =
740742 container_of (work , struct mlxsw_sp_acl_tcam_vregion ,
741743 rehash .dw .work );
744+ int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS ;
745+ int err ;
742746
743- mlxsw_sp_acl_tcam_vregion_rehash (vregion -> mlxsw_sp , vregion );
744- mlxsw_sp_acl_tcam_vregion_rehash_work_schedule (vregion );
747+ err = mlxsw_sp_acl_tcam_vregion_rehash (vregion -> mlxsw_sp ,
748+ vregion , & credits );
749+ if (credits < 0 )
750+ /* Rehash gone out of credits so it was interrupted.
751+ * Schedule the work as soon as possible to continue.
752+ */
753+ mlxsw_core_schedule_dw (& vregion -> rehash .dw , 0 );
754+ else
755+ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule (vregion );
745756}
746757
747758static struct mlxsw_sp_acl_tcam_vregion *
@@ -1176,14 +1187,18 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
11761187static int
11771188mlxsw_sp_acl_tcam_ventry_migrate (struct mlxsw_sp * mlxsw_sp ,
11781189 struct mlxsw_sp_acl_tcam_ventry * ventry ,
1179- struct mlxsw_sp_acl_tcam_chunk * chunk )
1190+ struct mlxsw_sp_acl_tcam_chunk * chunk ,
1191+ int * credits )
11801192{
11811193 struct mlxsw_sp_acl_tcam_entry * new_entry ;
11821194
11831195 /* First check if the entry is not already where we want it to be. */
11841196 if (ventry -> entry -> chunk == chunk )
11851197 return 0 ;
11861198
1199+ if (-- (* credits ) < 0 )
1200+ return 0 ;
1201+
11871202 new_entry = mlxsw_sp_acl_tcam_entry_create (mlxsw_sp , ventry , chunk );
11881203 if (IS_ERR (new_entry ))
11891204 return PTR_ERR (new_entry );
@@ -1223,7 +1238,8 @@ static int
12231238mlxsw_sp_acl_tcam_vchunk_migrate_one (struct mlxsw_sp * mlxsw_sp ,
12241239 struct mlxsw_sp_acl_tcam_vchunk * vchunk ,
12251240 struct mlxsw_sp_acl_tcam_region * region ,
1226- struct mlxsw_sp_acl_tcam_rehash_ctx * ctx )
1241+ struct mlxsw_sp_acl_tcam_rehash_ctx * ctx ,
1242+ int * credits )
12271243{
12281244 struct mlxsw_sp_acl_tcam_ventry * ventry ;
12291245 int err ;
@@ -1240,7 +1256,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
12401256
12411257 list_for_each_entry (ventry , & vchunk -> ventry_list , list ) {
12421258 err = mlxsw_sp_acl_tcam_ventry_migrate (mlxsw_sp , ventry ,
1243- vchunk -> chunk );
1259+ vchunk -> chunk , credits );
12441260 if (err ) {
12451261 if (ctx -> this_is_rollback )
12461262 return err ;
@@ -1250,6 +1266,11 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
12501266 */
12511267 swap (vchunk -> chunk , vchunk -> chunk2 );
12521268 return err ;
1269+ } else if (* credits < 0 ) {
1270+ /* We are out of credits, the rest of the ventries
1271+ * will be migrated later.
1272+ */
1273+ return 0 ;
12531274 }
12541275 }
12551276
@@ -1260,16 +1281,17 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
12601281static int
12611282mlxsw_sp_acl_tcam_vchunk_migrate_all (struct mlxsw_sp * mlxsw_sp ,
12621283 struct mlxsw_sp_acl_tcam_vregion * vregion ,
1263- struct mlxsw_sp_acl_tcam_rehash_ctx * ctx )
1284+ struct mlxsw_sp_acl_tcam_rehash_ctx * ctx ,
1285+ int * credits )
12641286{
12651287 struct mlxsw_sp_acl_tcam_vchunk * vchunk ;
12661288 int err ;
12671289
12681290 list_for_each_entry (vchunk , & vregion -> vchunk_list , list ) {
12691291 err = mlxsw_sp_acl_tcam_vchunk_migrate_one (mlxsw_sp , vchunk ,
12701292 vregion -> region ,
1271- ctx );
1272- if (err )
1293+ ctx , credits );
1294+ if (err || * credits < 0 )
12731295 return err ;
12741296 }
12751297 return 0 ;
@@ -1278,21 +1300,24 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
12781300static int
12791301mlxsw_sp_acl_tcam_vregion_migrate (struct mlxsw_sp * mlxsw_sp ,
12801302 struct mlxsw_sp_acl_tcam_vregion * vregion ,
1281- struct mlxsw_sp_acl_tcam_rehash_ctx * ctx )
1303+ struct mlxsw_sp_acl_tcam_rehash_ctx * ctx ,
1304+ int * credits )
12821305{
12831306 int err , err2 ;
12841307
12851308 trace_mlxsw_sp_acl_tcam_vregion_migrate (mlxsw_sp , vregion );
12861309 mutex_lock (& vregion -> lock );
1287- err = mlxsw_sp_acl_tcam_vchunk_migrate_all (mlxsw_sp , vregion , ctx );
1310+ err = mlxsw_sp_acl_tcam_vchunk_migrate_all (mlxsw_sp , vregion ,
1311+ ctx , credits );
12881312 if (err ) {
12891313 /* In case migration was not successful, we need to swap
12901314 * so the original region pointer is assigned again
12911315 * to vregion->region.
12921316 */
12931317 swap (vregion -> region , vregion -> region2 );
12941318 ctx -> this_is_rollback = true;
1295- err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all (mlxsw_sp , vregion , ctx );
1319+ err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all (mlxsw_sp , vregion ,
1320+ ctx , credits );
12961321 if (err2 )
12971322 vregion -> failed_rollback = true;
12981323 }
@@ -1301,6 +1326,12 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
13011326 return err ;
13021327}
13031328
1329+ static bool
1330+ mlxsw_sp_acl_tcam_vregion_rehash_in_progress (const struct mlxsw_sp_acl_tcam_rehash_ctx * ctx )
1331+ {
1332+ return ctx -> hints_priv ;
1333+ }
1334+
13041335static int
13051336mlxsw_sp_acl_tcam_vregion_rehash_start (struct mlxsw_sp * mlxsw_sp ,
13061337 struct mlxsw_sp_acl_tcam_vregion * vregion ,
@@ -1372,19 +1403,28 @@ mlxsw_sp_acl_tcam_vregion_rehash_end(struct mlxsw_sp *mlxsw_sp,
13721403
13731404static int
13741405mlxsw_sp_acl_tcam_vregion_rehash (struct mlxsw_sp * mlxsw_sp ,
1375- struct mlxsw_sp_acl_tcam_vregion * vregion )
1406+ struct mlxsw_sp_acl_tcam_vregion * vregion ,
1407+ int * credits )
13761408{
13771409 struct mlxsw_sp_acl_tcam_rehash_ctx * ctx = & vregion -> rehash .ctx ;
13781410 int err ;
13791411
1380- err = mlxsw_sp_acl_tcam_vregion_rehash_start (mlxsw_sp , vregion , ctx );
1381- if (err ) {
1382- if (err != - EAGAIN )
1383- dev_err (mlxsw_sp -> bus_info -> dev , "Failed get rehash hints\n" );
1384- return err ;
1412+ /* Check if the previous rehash work was interrupted
1413+ * which means we have to continue it now.
1414+ * If not, start a new rehash.
1415+ */
1416+ if (!mlxsw_sp_acl_tcam_vregion_rehash_in_progress (ctx )) {
1417+ err = mlxsw_sp_acl_tcam_vregion_rehash_start (mlxsw_sp ,
1418+ vregion , ctx );
1419+ if (err ) {
1420+ if (err != - EAGAIN )
1421+ dev_err (mlxsw_sp -> bus_info -> dev , "Failed get rehash hints\n" );
1422+ return err ;
1423+ }
13851424 }
13861425
1387- err = mlxsw_sp_acl_tcam_vregion_migrate (mlxsw_sp , vregion , ctx );
1426+ err = mlxsw_sp_acl_tcam_vregion_migrate (mlxsw_sp , vregion ,
1427+ ctx , credits );
13881428 if (err ) {
13891429 dev_err (mlxsw_sp -> bus_info -> dev , "Failed to migrate vregion\n" );
13901430 if (vregion -> failed_rollback ) {
@@ -1394,7 +1434,9 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
13941434 }
13951435 }
13961436
1397- mlxsw_sp_acl_tcam_vregion_rehash_end (mlxsw_sp , vregion , ctx );
1437+ if (* credits >= 0 )
1438+ mlxsw_sp_acl_tcam_vregion_rehash_end (mlxsw_sp , vregion , ctx );
1439+
13981440 return err ;
13991441}
14001442
0 commit comments