Przeglądaj źródła

[arbel] Allocate only as much memory as is needed for firmware and ICM

Use individual page mappings rather than a single whole-region
mapping, to avoid the waste of memory that occurs due to the
constraint that each mapped block must be aligned on its own size.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 lat temu
rodzic
commit
62115cf437
1 zmienionych plików z 66 dodań i 26 usunięć
  1. 66
    26
      src/drivers/infiniband/arbel.c

+ 66
- 26
src/drivers/infiniband/arbel.c Wyświetl plik

@@ -1967,6 +1967,55 @@ static struct ib_device_operations arbel_ib_operations = {
1967 1967
  ***************************************************************************
1968 1968
  */
1969 1969
 
1970
+/**
1971
+ * Map virtual to physical address for firmware usage
1972
+ *
1973
+ * @v arbel		Arbel device
1974
+ * @v map		Mapping function
1975
+ * @v va		Virtual address
1976
+ * @v pa		Physical address
1977
+ * @v len		Length of region
1978
+ * @ret rc		Return status code
1979
+ */
1980
+static int arbel_map_vpm ( struct arbel *arbel,
1981
+			   int ( *map ) ( struct arbel *arbel,
1982
+			     const struct arbelprm_virtual_physical_mapping* ),
1983
+			   uint64_t va, physaddr_t pa, size_t len ) {
1984
+	struct arbelprm_virtual_physical_mapping mapping;
1985
+	int rc;
1986
+
1987
+	assert ( ( va & ( ARBEL_PAGE_SIZE - 1 ) ) == 0 );
1988
+	assert ( ( pa & ( ARBEL_PAGE_SIZE - 1 ) ) == 0 );
1989
+	assert ( ( len & ( ARBEL_PAGE_SIZE - 1 ) ) == 0 );
1990
+
1991
+	/* These mappings tend to generate huge volumes of
1992
+	 * uninteresting debug data, which basically makes it
1993
+	 * impossible to use debugging otherwise.
1994
+	 */
1995
+	DBG_DISABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
1996
+
1997
+	while ( len ) {
1998
+		memset ( &mapping, 0, sizeof ( mapping ) );
1999
+		MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
2000
+		MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
2001
+		MLX_FILL_2 ( &mapping, 3,
2002
+			     log2size, 0,
2003
+			     pa_l, ( pa >> 12 ) );
2004
+		if ( ( rc = map ( arbel, &mapping ) ) != 0 ) {
2005
+			DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
2006
+			DBGC ( arbel, "Arbel %p could not map %llx => %lx: "
2007
+			       "%s\n", arbel, va, pa, strerror ( rc ) );
2008
+			return rc;
2009
+		}
2010
+		pa += ARBEL_PAGE_SIZE;
2011
+		va += ARBEL_PAGE_SIZE;
2012
+		len -= ARBEL_PAGE_SIZE;
2013
+	}
2014
+
2015
+	DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
2016
+	return 0;
2017
+}
2018
+
1970 2019
 /**
1971 2020
  * Start firmware running
1972 2021
  *
@@ -1976,7 +2025,6 @@ static struct ib_device_operations arbel_ib_operations = {
1976 2025
 static int arbel_start_firmware ( struct arbel *arbel ) {
1977 2026
 	struct arbelprm_query_fw fw;
1978 2027
 	struct arbelprm_access_lam lam;
1979
-	struct arbelprm_virtual_physical_mapping map_fa;
1980 2028
 	unsigned int fw_pages;
1981 2029
 	unsigned int log2_fw_pages;
1982 2030
 	size_t fw_size;
@@ -2010,20 +2058,16 @@ static int arbel_start_firmware ( struct arbel *arbel ) {
2010 2058
 
2011 2059
 	/* Allocate firmware pages and map firmware area */
2012 2060
 	fw_size = ( fw_pages * ARBEL_PAGE_SIZE );
2013
-	arbel->firmware_area = umalloc ( fw_size * 2 );
2061
+	arbel->firmware_area = umalloc ( fw_size );
2014 2062
 	if ( ! arbel->firmware_area ) {
2015 2063
 		rc = -ENOMEM;
2016 2064
 		goto err_alloc_fa;
2017 2065
 	}
2018
-	fw_base = ( user_to_phys ( arbel->firmware_area, fw_size ) &
2019
-		    ~( fw_size - 1 ) );
2066
+	fw_base = user_to_phys ( arbel->firmware_area, 0 );
2020 2067
 	DBGC ( arbel, "Arbel %p firmware area at [%08lx,%08lx)\n",
2021 2068
 	       arbel, fw_base, ( fw_base + fw_size ) );
2022
-	memset ( &map_fa, 0, sizeof ( map_fa ) );
2023
-	MLX_FILL_2 ( &map_fa, 3,
2024
-		     log2size, log2_fw_pages,
2025
-		     pa_l, ( fw_base >> 12 ) );
2026
-	if ( ( rc = arbel_cmd_map_fa ( arbel, &map_fa ) ) != 0 ) {
2069
+	if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_fa,
2070
+				    0, fw_base, fw_size ) ) != 0 ) {
2027 2071
 		DBGC ( arbel, "Arbel %p could not map firmware: %s\n",
2028 2072
 		       arbel, strerror ( rc ) );
2029 2073
 		goto err_map_fa;
@@ -2168,8 +2212,6 @@ static int arbel_alloc_icm ( struct arbel *arbel,
2168 2212
 			     struct arbelprm_init_hca *init_hca ) {
2169 2213
 	struct arbelprm_scalar_parameter icm_size;
2170 2214
 	struct arbelprm_scalar_parameter icm_aux_size;
2171
-	struct arbelprm_virtual_physical_mapping map_icm_aux;
2172
-	struct arbelprm_virtual_physical_mapping map_icm;
2173 2215
 	union arbelprm_doorbell_record *db_rec;
2174 2216
 	size_t icm_offset = 0;
2175 2217
 	unsigned int log_num_uars, log_num_qps, log_num_srqs, log_num_ees;
@@ -2177,6 +2219,7 @@ static int arbel_alloc_icm ( struct arbel *arbel,
2177 2219
 	unsigned int log_num_eqs, log_num_mcs;
2178 2220
 	size_t db_rec_offset;
2179 2221
 	size_t len;
2222
+	physaddr_t icm_phys;
2180 2223
 	int rc;
2181 2224
 
2182 2225
 	/* Queue pair contexts */
@@ -2379,35 +2422,32 @@ static int arbel_alloc_icm ( struct arbel *arbel,
2379 2422
 		rc = -ENOMEM;
2380 2423
 		goto err_alloc;
2381 2424
 	}
2425
+	icm_phys = user_to_phys ( arbel->icm, 0 );
2382 2426
 
2383 2427
 	/* Map ICM auxiliary area */
2384
-	memset ( &map_icm_aux, 0, sizeof ( map_icm_aux ) );
2385
-	MLX_FILL_2 ( &map_icm_aux, 3,
2386
-		     log2size,
2387
-		     fls ( ( arbel->icm_aux_len / ARBEL_PAGE_SIZE ) - 1 ),
2388
-		     pa_l,
2389
-		     ( user_to_phys ( arbel->icm, arbel->icm_len ) >> 12 ) );
2390
-	if ( ( rc = arbel_cmd_map_icm_aux ( arbel, &map_icm_aux ) ) != 0 ) {
2428
+	DBGC ( arbel, "Arbel %p ICM AUX at [%08lx,%08lx)\n",
2429
+	       arbel, icm_phys, ( icm_phys + arbel->icm_aux_len ) );
2430
+	if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_icm_aux,
2431
+				    0, icm_phys, arbel->icm_aux_len ) ) != 0 ){
2391 2432
 		DBGC ( arbel, "Arbel %p could not map AUX ICM: %s\n",
2392 2433
 		       arbel, strerror ( rc ) );
2393 2434
 		goto err_map_icm_aux;
2394 2435
 	}
2436
+	icm_phys += arbel->icm_aux_len;
2395 2437
 
2396 2438
 	/* MAP ICM area */
2397
-	memset ( &map_icm, 0, sizeof ( map_icm ) );
2398
-	MLX_FILL_2 ( &map_icm, 3,
2399
-		     log2size,
2400
-		     fls ( ( arbel->icm_len / ARBEL_PAGE_SIZE ) - 1 ),
2401
-		     pa_l, ( user_to_phys ( arbel->icm, 0 ) >> 12 ) );
2402
-	if ( ( rc = arbel_cmd_map_icm ( arbel, &map_icm ) ) != 0 ) {
2439
+	DBGC ( arbel, "Arbel %p ICM at [%08lx,%08lx)\n",
2440
+	       arbel, icm_phys, ( icm_phys + arbel->icm_len ) );
2441
+	if ( ( rc = arbel_map_vpm ( arbel, arbel_cmd_map_icm,
2442
+				    0, icm_phys, arbel->icm_len ) ) != 0 ) {
2403 2443
 		DBGC ( arbel, "Arbel %p could not map ICM: %s\n",
2404 2444
 		       arbel, strerror ( rc ) );
2405 2445
 		goto err_map_icm;
2406 2446
 	}
2447
+	arbel->db_rec = phys_to_virt ( icm_phys + db_rec_offset );
2448
+	icm_phys += arbel->icm_len;
2407 2449
 
2408 2450
 	/* Initialise doorbell records */
2409
-	arbel->db_rec =
2410
-		phys_to_virt ( user_to_phys ( arbel->icm, db_rec_offset ) );
2411 2451
 	memset ( arbel->db_rec, 0, ARBEL_PAGE_SIZE );
2412 2452
 	db_rec = &arbel->db_rec[ARBEL_GROUP_SEPARATOR_DOORBELL];
2413 2453
 	MLX_FILL_1 ( &db_rec->qp, 1, res, ARBEL_UAR_RES_GROUP_SEP );

Ładowanie…
Anuluj
Zapisz