@@ -73,7 +73,7 @@ MODULE_VERSION(NTB_TRANSPORT_VER);
7373MODULE_LICENSE ("Dual BSD/GPL" );
7474MODULE_AUTHOR ("Intel Corporation" );
7575
76- static unsigned long max_mw_size ;
76+ static unsigned long max_mw_size = 256 * 1024 * 1024 ;
7777module_param (max_mw_size , ulong , 0644 );
7878MODULE_PARM_DESC (max_mw_size , "Limit size of large memory windows" );
7979
@@ -927,8 +927,8 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
927927 xlat_size = round_up (size , xlat_align_size );
928928 buff_size = round_up (size , xlat_align );
929929
930- /* No need to re-setup */
931- if (mw -> xlat_size == xlat_size )
930+ /* No need to re-setup if size already matches */
931+ if (mw -> xlat_size == xlat_size && mw -> buff_size == buff_size )
932932 return 0 ;
933933
934934 if (mw -> buff_size )
@@ -1048,8 +1048,11 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
10481048 if (!nt -> link_is_up )
10491049 cancel_delayed_work_sync (& nt -> link_work );
10501050
1051- for (i = 0 ; i < nt -> mw_count ; i ++ )
1052- ntb_free_mw (nt , i );
1051+ /*
1052+ * Do NOT free MW memory on link down. Memory is retained across
1053+ * link cycles to avoid fragmentation from repeated allocation.
1054+ * Memory is only freed on device removal in ntb_transport_free().
1055+ */
10531056
10541057 /* The scratchpad registers keep the values if the remote side
10551058 * goes down, blast them now to give them a sane value the next
@@ -1332,6 +1335,34 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
13321335 return 0 ;
13331336}
13341337
1338+ /*
1339+ * Speculatively pre-allocate memory assuming symmetric config.
1340+ * This grabs contiguous memory early before fragmentation.
1341+ * If peer has different size, we'll reallocate on link-up.
1342+ */
1343+ static void ntb_preallocate_mws (struct ntb_transport_ctx * nt )
1344+ {
1345+ struct ntb_transport_mw * mw ;
1346+ resource_size_t size ;
1347+ int i , rc ;
1348+
1349+ for (i = 0 ; i < nt -> mw_count ; i ++ ) {
1350+ mw = & nt -> mw_vec [i ];
1351+ size = mw -> phys_size ;
1352+
1353+ if (max_mw_size && size > max_mw_size )
1354+ size = max_mw_size ;
1355+
1356+ rc = ntb_set_mw (nt , i , size );
1357+ if (rc ) {
1358+ dev_info (& nt -> ndev -> pdev -> dev ,
1359+ "Failed to preallocate MW%d (size %llx): %d\n" ,
1360+ i , (unsigned long long )size , rc );
1361+ /* Continue - link-up will retry */
1362+ }
1363+ }
1364+ }
1365+
13351366static int ntb_transport_probe (struct ntb_client * self , struct ntb_dev * ndev )
13361367{
13371368 struct ntb_transport_ctx * nt ;
@@ -1476,6 +1507,9 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
14761507 INIT_WORK (& nt -> link_cleanup , ntb_transport_link_cleanup_work );
14771508 nt -> link_is_up = false;
14781509
1510+ /* Speculatively pre-allocate MW buffers to avoid fragmentation */
1511+ ntb_preallocate_mws (nt );
1512+
14791513 rc = ntb_set_ctx (ndev , nt , & ntb_transport_ops );
14801514 if (rc )
14811515 goto err2 ;
@@ -1495,9 +1529,11 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
14951529err2 :
14961530 kfree (nt -> qp_vec );
14971531err1 :
1498- while (i -- ) {
1532+ for (i = 0 ; i < mw_count ; i ++ ) {
14991533 mw = & nt -> mw_vec [i ];
1500- iounmap (mw -> vbase );
1534+ ntb_free_mw (nt , i );
1535+ if (mw -> vbase )
1536+ iounmap (mw -> vbase );
15011537 }
15021538 kfree (nt -> mw_vec );
15031539err :
0 commit comments