|
@@ -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 );
|