@@ -74,7 +74,7 @@ MODULE_VERSION(NTB_TRANSPORT_VER);
7474MODULE_LICENSE ("Dual BSD/GPL" );
7575MODULE_AUTHOR ("Intel Corporation" );
7676
77- static unsigned long max_mw_size ;
77+ static unsigned long max_mw_size = 256 * 1024 * 1024 ;
7878module_param (max_mw_size , ulong , 0644 );
7979MODULE_PARM_DESC (max_mw_size , "Limit size of large memory windows" );
8080
@@ -931,8 +931,8 @@ static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
931931 xlat_size = round_up (size , xlat_align_size );
932932 buff_size = round_up (size , xlat_align );
933933
934- /* No need to re-setup */
935- if (mw -> xlat_size == xlat_size )
934+ /* No need to re-setup if size already matches */
935+ if (mw -> xlat_size == xlat_size && mw -> buff_size == buff_size )
936936 return 0 ;
937937
938938 if (mw -> buff_size )
@@ -1052,8 +1052,11 @@ static void ntb_transport_link_cleanup(struct ntb_transport_ctx *nt)
10521052 if (!nt -> link_is_up )
10531053 cancel_delayed_work_sync (& nt -> link_work );
10541054
1055- for (i = 0 ; i < nt -> mw_count ; i ++ )
1056- ntb_free_mw (nt , i );
1055+ /*
1056+ * Do NOT free MW memory on link down. Memory is retained across
1057+ * link cycles to avoid fragmentation from repeated allocation.
1058+ * Memory is only freed on device removal in ntb_transport_free().
1059+ */
10571060
10581061 /* The scratchpad registers keep the values if the remote side
10591062 * goes down, blast them now to give them a sane value the next
@@ -1339,6 +1342,34 @@ static int ntb_transport_init_queue(struct ntb_transport_ctx *nt,
13391342 return 0 ;
13401343}
13411344
1345+ /*
1346+ * Speculatively pre-allocate memory assuming symmetric config.
1347+ * This grabs contiguous memory early before fragmentation.
1348+ * If peer has different size, we'll reallocate on link-up.
1349+ */
1350+ static void ntb_preallocate_mws (struct ntb_transport_ctx * nt )
1351+ {
1352+ struct ntb_transport_mw * mw ;
1353+ resource_size_t size ;
1354+ int i , rc ;
1355+
1356+ for (i = 0 ; i < nt -> mw_count ; i ++ ) {
1357+ mw = & nt -> mw_vec [i ];
1358+ size = mw -> phys_size ;
1359+
1360+ if (max_mw_size && size > max_mw_size )
1361+ size = max_mw_size ;
1362+
1363+ rc = ntb_set_mw (nt , i , size );
1364+ if (rc ) {
1365+ dev_info (& nt -> ndev -> pdev -> dev ,
1366+ "Failed to preallocate MW%d (size %llx): %d\n" ,
1367+ i , (unsigned long long )size , rc );
1368+ /* Continue - link-up will retry */
1369+ }
1370+ }
1371+ }
1372+
13421373static int ntb_transport_probe (struct ntb_client * self , struct ntb_dev * ndev )
13431374{
13441375 struct ntb_transport_ctx * nt ;
@@ -1484,6 +1515,9 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
14841515 INIT_WORK (& nt -> link_cleanup , ntb_transport_link_cleanup_work );
14851516 nt -> link_is_up = false;
14861517
1518+ /* Speculatively pre-allocate MW buffers to avoid fragmentation */
1519+ ntb_preallocate_mws (nt );
1520+
14871521 rc = ntb_set_ctx (ndev , nt , & ntb_transport_ops );
14881522 if (rc )
14891523 goto err2 ;
@@ -1503,9 +1537,11 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
15031537err2 :
15041538 kfree (nt -> qp_vec );
15051539err1 :
1506- while (i -- ) {
1540+ for (i = 0 ; i < mw_count ; i ++ ) {
15071541 mw = & nt -> mw_vec [i ];
1508- iounmap (mw -> vbase );
1542+ ntb_free_mw (nt , i );
1543+ if (mw -> vbase )
1544+ iounmap (mw -> vbase );
15091545 }
15101546 kfree (nt -> mw_vec );
15111547err :
0 commit comments