Browse Source

[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 years ago
parent
commit
62115cf437
1 changed files with 66 additions and 26 deletions
  1. 66
    26
      src/drivers/infiniband/arbel.c

+ 66
- 26
src/drivers/infiniband/arbel.c View File

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
  * Start firmware running
2020
  * Start firmware running
1972
  *
2021
  *
1976
 static int arbel_start_firmware ( struct arbel *arbel ) {
2025
 static int arbel_start_firmware ( struct arbel *arbel ) {
1977
 	struct arbelprm_query_fw fw;
2026
 	struct arbelprm_query_fw fw;
1978
 	struct arbelprm_access_lam lam;
2027
 	struct arbelprm_access_lam lam;
1979
-	struct arbelprm_virtual_physical_mapping map_fa;
1980
 	unsigned int fw_pages;
2028
 	unsigned int fw_pages;
1981
 	unsigned int log2_fw_pages;
2029
 	unsigned int log2_fw_pages;
1982
 	size_t fw_size;
2030
 	size_t fw_size;
2010
 
2058
 
2011
 	/* Allocate firmware pages and map firmware area */
2059
 	/* Allocate firmware pages and map firmware area */
2012
 	fw_size = ( fw_pages * ARBEL_PAGE_SIZE );
2060
 	fw_size = ( fw_pages * ARBEL_PAGE_SIZE );
2013
-	arbel->firmware_area = umalloc ( fw_size * 2 );
2061
+	arbel->firmware_area = umalloc ( fw_size );
2014
 	if ( ! arbel->firmware_area ) {
2062
 	if ( ! arbel->firmware_area ) {
2015
 		rc = -ENOMEM;
2063
 		rc = -ENOMEM;
2016
 		goto err_alloc_fa;
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
 	DBGC ( arbel, "Arbel %p firmware area at [%08lx,%08lx)\n",
2067
 	DBGC ( arbel, "Arbel %p firmware area at [%08lx,%08lx)\n",
2021
 	       arbel, fw_base, ( fw_base + fw_size ) );
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
 		DBGC ( arbel, "Arbel %p could not map firmware: %s\n",
2071
 		DBGC ( arbel, "Arbel %p could not map firmware: %s\n",
2028
 		       arbel, strerror ( rc ) );
2072
 		       arbel, strerror ( rc ) );
2029
 		goto err_map_fa;
2073
 		goto err_map_fa;
2168
 			     struct arbelprm_init_hca *init_hca ) {
2212
 			     struct arbelprm_init_hca *init_hca ) {
2169
 	struct arbelprm_scalar_parameter icm_size;
2213
 	struct arbelprm_scalar_parameter icm_size;
2170
 	struct arbelprm_scalar_parameter icm_aux_size;
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
 	union arbelprm_doorbell_record *db_rec;
2215
 	union arbelprm_doorbell_record *db_rec;
2174
 	size_t icm_offset = 0;
2216
 	size_t icm_offset = 0;
2175
 	unsigned int log_num_uars, log_num_qps, log_num_srqs, log_num_ees;
2217
 	unsigned int log_num_uars, log_num_qps, log_num_srqs, log_num_ees;
2177
 	unsigned int log_num_eqs, log_num_mcs;
2219
 	unsigned int log_num_eqs, log_num_mcs;
2178
 	size_t db_rec_offset;
2220
 	size_t db_rec_offset;
2179
 	size_t len;
2221
 	size_t len;
2222
+	physaddr_t icm_phys;
2180
 	int rc;
2223
 	int rc;
2181
 
2224
 
2182
 	/* Queue pair contexts */
2225
 	/* Queue pair contexts */
2379
 		rc = -ENOMEM;
2422
 		rc = -ENOMEM;
2380
 		goto err_alloc;
2423
 		goto err_alloc;
2381
 	}
2424
 	}
2425
+	icm_phys = user_to_phys ( arbel->icm, 0 );
2382
 
2426
 
2383
 	/* Map ICM auxiliary area */
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
 		DBGC ( arbel, "Arbel %p could not map AUX ICM: %s\n",
2432
 		DBGC ( arbel, "Arbel %p could not map AUX ICM: %s\n",
2392
 		       arbel, strerror ( rc ) );
2433
 		       arbel, strerror ( rc ) );
2393
 		goto err_map_icm_aux;
2434
 		goto err_map_icm_aux;
2394
 	}
2435
 	}
2436
+	icm_phys += arbel->icm_aux_len;
2395
 
2437
 
2396
 	/* MAP ICM area */
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
 		DBGC ( arbel, "Arbel %p could not map ICM: %s\n",
2443
 		DBGC ( arbel, "Arbel %p could not map ICM: %s\n",
2404
 		       arbel, strerror ( rc ) );
2444
 		       arbel, strerror ( rc ) );
2405
 		goto err_map_icm;
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
 	/* Initialise doorbell records */
2450
 	/* Initialise doorbell records */
2409
-	arbel->db_rec =
2410
-		phys_to_virt ( user_to_phys ( arbel->icm, db_rec_offset ) );
2411
 	memset ( arbel->db_rec, 0, ARBEL_PAGE_SIZE );
2451
 	memset ( arbel->db_rec, 0, ARBEL_PAGE_SIZE );
2412
 	db_rec = &arbel->db_rec[ARBEL_GROUP_SEPARATOR_DOORBELL];
2452
 	db_rec = &arbel->db_rec[ARBEL_GROUP_SEPARATOR_DOORBELL];
2413
 	MLX_FILL_1 ( &db_rec->qp, 1, res, ARBEL_UAR_RES_GROUP_SEP );
2453
 	MLX_FILL_1 ( &db_rec->qp, 1, res, ARBEL_UAR_RES_GROUP_SEP );

Loading…
Cancel
Save