]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[arbel] Perform ICM allocations according to the specification
authorMichael Brown <mcb30@ipxe.org>
Fri, 17 Sep 2010 03:56:23 +0000 (04:56 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 17 Sep 2010 04:51:34 +0000 (05:51 +0100)
The current method for ICM allocation exactly matches the addresses
chosen by the old Etherboot driver, but does not match the
specification.  Some ICM tables (notably the queue pair context table)
therefore end up incorrectly aligned.

Fix by performing allocations as per the specification.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/infiniband/arbel.c
src/drivers/infiniband/arbel.h

index 6a7816206e029839ceaac4aa9941de7bb81de17a..e206a6fe23272e5f1f3c4b9f25b0af29d91aab45 100644 (file)
@@ -1981,7 +1981,7 @@ static int arbel_start_firmware ( struct arbel *arbel ) {
        arbel_cmd_enable_lam ( arbel, &lam );
 
        /* Allocate firmware pages and map firmware area */
-       fw_size = ( fw_pages * 4096 );
+       fw_size = ( fw_pages * ARBEL_PAGE_SIZE );
        arbel->firmware_area = umalloc ( fw_size * 2 );
        if ( ! arbel->firmware_area ) {
                rc = -ENOMEM;
@@ -2092,18 +2092,17 @@ static int arbel_get_limits ( struct arbel *arbel ) {
 }
 
 /**
- * Get ICM usage
+ * Align ICM table
  *
- * @v log_num_entries  Log2 of the number of entries
- * @v entry_size       Entry size
- * @ret usage          Usage size in ICM
+ * @v icm_offset       Current ICM offset
+ * @v len              ICM table length
+ * @ret icm_offset     ICM offset
  */
-static size_t icm_usage ( unsigned int log_num_entries, size_t entry_size ) {
-       size_t usage;
+static size_t icm_align ( size_t icm_offset, size_t len ) {
 
-       usage = ( ( 1 << log_num_entries ) * entry_size );
-       usage = ( ( usage + 4095 ) & ~4095 );
-       return usage;
+       /* Round up to a multiple of the table size */
+       assert ( len == ( 1UL << ( fls ( len ) - 1 ) ) );
+       return ( ( icm_offset + len - 1 ) & ~( len - 1 ) );
 }
 
 /**
@@ -2123,6 +2122,8 @@ static int arbel_alloc_icm ( struct arbel *arbel,
        size_t icm_offset = 0;
        unsigned int log_num_qps, log_num_srqs, log_num_ees, log_num_cqs;
        unsigned int log_num_mtts, log_num_mpts, log_num_rdbs, log_num_eqs;
+       unsigned int log_num_mcs;
+       size_t len;
        int rc;
 
        icm_offset = ( ( arbel->limits.reserved_uars + 1 ) << 12 );
@@ -2130,108 +2131,143 @@ static int arbel_alloc_icm ( struct arbel *arbel,
        /* Queue pair contexts */
        log_num_qps = fls ( arbel->limits.reserved_qps +
                            ARBEL_RSVD_SPECIAL_QPS + ARBEL_MAX_QPS - 1 );
+       len = ( ( 1 << log_num_qps ) * arbel->limits.qpc_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_2 ( init_hca, 13,
                     qpc_eec_cqc_eqc_rdb_parameters.qpc_base_addr_l,
                     ( icm_offset >> 7 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_qp,
                     log_num_qps );
-       DBGC ( arbel, "Arbel %p ICM QPC base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_qps, arbel->limits.qpc_entry_size );
+       DBGC ( arbel, "Arbel %p ICM QPC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Extended queue pair contexts */
+       len = ( ( 1 << log_num_qps ) * arbel->limits.eqpc_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 25,
                     qpc_eec_cqc_eqc_rdb_parameters.eqpc_base_addr_l,
                     icm_offset );
-       DBGC ( arbel, "Arbel %p ICM EQPC base = %zx\n", arbel, icm_offset );
-       //      icm_offset += icm_usage ( log_num_qps, arbel->limits.eqpc_entry_size );
-       icm_offset += icm_usage ( log_num_qps, arbel->limits.qpc_entry_size );  
+       DBGC ( arbel, "Arbel %p ICM EQPC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Shared receive queue contexts */
        log_num_srqs = fls ( arbel->limits.reserved_srqs - 1 );
+       len = ( ( 1 << log_num_srqs ) * arbel->limits.srqc_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_2 ( init_hca, 19,
                     qpc_eec_cqc_eqc_rdb_parameters.srqc_base_addr_l,
                     ( icm_offset >> 5 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_srq,
                     log_num_srqs );
-       DBGC ( arbel, "Arbel %p ICM SRQC base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_srqs, arbel->limits.srqc_entry_size );
+       DBGC ( arbel, "Arbel %p ICM SRQC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* End-to-end contexts */
        log_num_ees = fls ( arbel->limits.reserved_ees - 1 );
+       len = ( ( 1 << log_num_ees ) * arbel->limits.eec_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_2 ( init_hca, 17,
                     qpc_eec_cqc_eqc_rdb_parameters.eec_base_addr_l,
                     ( icm_offset >> 7 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_ee,
                     log_num_ees );
-       DBGC ( arbel, "Arbel %p ICM EEC base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_ees, arbel->limits.eec_entry_size );
+       DBGC ( arbel, "Arbel %p ICM EEC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Extended end-to-end contexts */
+       len = ( ( 1 << log_num_ees ) * arbel->limits.eeec_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 29,
                     qpc_eec_cqc_eqc_rdb_parameters.eeec_base_addr_l,
                     icm_offset );
-       DBGC ( arbel, "Arbel %p ICM EEEC base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_ees, arbel->limits.eeec_entry_size );
+       DBGC ( arbel, "Arbel %p ICM EEEC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Completion queue contexts */
        log_num_cqs = fls ( arbel->limits.reserved_cqs + ARBEL_MAX_CQS - 1 );
+       len = ( ( 1 << log_num_cqs ) * arbel->limits.cqc_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_2 ( init_hca, 21,
                     qpc_eec_cqc_eqc_rdb_parameters.cqc_base_addr_l,
                     ( icm_offset >> 6 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_of_cq,
                     log_num_cqs );
-       DBGC ( arbel, "Arbel %p ICM CQC base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_cqs, arbel->limits.cqc_entry_size );
+       DBGC ( arbel, "Arbel %p ICM CQC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Memory translation table */
        log_num_mtts = fls ( arbel->limits.reserved_mtts - 1 );
+       len = ( ( 1 << log_num_mtts ) * arbel->limits.mtt_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 65,
                     tpt_parameters.mtt_base_addr_l, icm_offset );
-       DBGC ( arbel, "Arbel %p ICM MTT base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_mtts, arbel->limits.mtt_entry_size );
+       DBGC ( arbel, "Arbel %p ICM MTT at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Memory protection table */
        log_num_mpts = fls ( arbel->limits.reserved_mrws + 1 - 1 );
+       len = ( ( 1 << log_num_mpts ) * arbel->limits.mpt_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 61,
                     tpt_parameters.mpt_base_adr_l, icm_offset );
        MLX_FILL_1 ( init_hca, 62,
                     tpt_parameters.log_mpt_sz, log_num_mpts );
-       DBGC ( arbel, "Arbel %p ICM MTT base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_mpts, arbel->limits.mpt_entry_size );
+       DBGC ( arbel, "Arbel %p ICM MTT at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
-       /* RDMA something or other */
+       /* Remote read data base table */
        log_num_rdbs = fls ( arbel->limits.reserved_rdbs - 1 );
+       len = ( ( 1 << log_num_rdbs ) * ARBEL_RDB_ENTRY_SIZE );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 37,
                     qpc_eec_cqc_eqc_rdb_parameters.rdb_base_addr_l,
                     icm_offset );
-       DBGC ( arbel, "Arbel %p ICM RDB base = %zx\n", arbel, icm_offset );
-       icm_offset += icm_usage ( log_num_rdbs, 32 );
+       DBGC ( arbel, "Arbel %p ICM RDB at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Event queue contexts */
-       log_num_eqs =  fls ( arbel->limits.reserved_eqs + ARBEL_MAX_EQS - 1 );
+       log_num_eqs = fls ( arbel->limits.reserved_eqs + ARBEL_MAX_EQS - 1 );
+       len = ( ( 1 << log_num_eqs ) * arbel->limits.eqc_entry_size );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_2 ( init_hca, 33,
                     qpc_eec_cqc_eqc_rdb_parameters.eqc_base_addr_l,
                     ( icm_offset >> 6 ),
                     qpc_eec_cqc_eqc_rdb_parameters.log_num_eq,
                     log_num_eqs );
-       DBGC ( arbel, "Arbel %p ICM EQ base = %zx\n", arbel, icm_offset );
-       icm_offset += ( ( 1 << log_num_eqs ) * arbel->limits.eqc_entry_size );
+       DBGC ( arbel, "Arbel %p ICM EQ at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
        /* Multicast table */
+       log_num_mcs = ARBEL_LOG_MULTICAST_HASH_SIZE;
+       len = ( ( 1 << log_num_mcs ) * sizeof ( struct arbelprm_mgm_entry ) );
+       icm_offset = icm_align ( icm_offset, len );
        MLX_FILL_1 ( init_hca, 49,
                     multicast_parameters.mc_base_addr_l, icm_offset );
        MLX_FILL_1 ( init_hca, 52,
                     multicast_parameters.log_mc_table_entry_sz,
                     fls ( sizeof ( struct arbelprm_mgm_entry ) - 1 ) );
        MLX_FILL_1 ( init_hca, 53,
-                    multicast_parameters.mc_table_hash_sz, 8 );
+                    multicast_parameters.mc_table_hash_sz,
+                    ( 1 << log_num_mcs ) );
        MLX_FILL_1 ( init_hca, 54,
-                    multicast_parameters.log_mc_table_sz, 3 );
-       DBGC ( arbel, "Arbel %p ICM MC base = %zx\n", arbel, icm_offset );
-       icm_offset += ( 8 * sizeof ( struct arbelprm_mgm_entry ) );
+                    multicast_parameters.log_mc_table_sz,
+                    log_num_mcs /* Only one entry per hash */ );
+       DBGC ( arbel, "Arbel %p ICM MC at [%zx,%zx)\n",
+              arbel, icm_offset, ( icm_offset + len ) );
+       icm_offset += len;
 
-       arbel->icm_len = icm_offset;
-       arbel->icm_len = ( ( arbel->icm_len + 4095 ) & ~4095 );
+       /* Round up to a whole number of pages */
+       arbel->icm_len = icm_align ( icm_offset, ARBEL_PAGE_SIZE );
 
        /* Get ICM auxiliary area size */
        memset ( &icm_size, 0, sizeof ( icm_size ) );
@@ -2242,7 +2278,8 @@ static int arbel_alloc_icm ( struct arbel *arbel,
                       arbel, strerror ( rc ) );
                goto err_set_icm_size;
        }
-       arbel->icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * 4096 );
+       arbel->icm_aux_len =
+               ( MLX_GET ( &icm_aux_size, value ) * ARBEL_PAGE_SIZE );
 
        /* Allocate ICM data and auxiliary area */
        DBGC ( arbel, "Arbel %p requires %zd kB ICM and %zd kB AUX ICM\n",
@@ -2257,7 +2294,8 @@ static int arbel_alloc_icm ( struct arbel *arbel,
        /* Map ICM auxiliary area */
        memset ( &map_icm_aux, 0, sizeof ( map_icm_aux ) );
        MLX_FILL_2 ( &map_icm_aux, 3,
-                    log2size, fls ( ( arbel->icm_aux_len / 4096 ) - 1 ),
+                    log2size,
+                    fls ( ( arbel->icm_aux_len / ARBEL_PAGE_SIZE ) - 1 ),
                     pa_l,
                     ( user_to_phys ( arbel->icm, arbel->icm_len ) >> 12 ) );
        if ( ( rc = arbel_cmd_map_icm_aux ( arbel, &map_icm_aux ) ) != 0 ) {
@@ -2269,7 +2307,8 @@ static int arbel_alloc_icm ( struct arbel *arbel,
        /* MAP ICM area */
        memset ( &map_icm, 0, sizeof ( map_icm ) );
        MLX_FILL_2 ( &map_icm, 3,
-                    log2size, fls ( ( arbel->icm_len / 4096 ) - 1 ),
+                    log2size,
+                    fls ( ( arbel->icm_len / ARBEL_PAGE_SIZE ) - 1 ),
                     pa_l, ( user_to_phys ( arbel->icm, 0 ) >> 12 ) );
        if ( ( rc = arbel_cmd_map_icm ( arbel, &map_icm ) ) != 0 ) {
                DBGC ( arbel, "Arbel %p could not map ICM: %s\n",
@@ -2287,7 +2326,7 @@ static int arbel_alloc_icm ( struct arbel *arbel,
 
        return 0;
 
-       arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / 4096 ) );
+       arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / ARBEL_PAGE_SIZE ) );
  err_map_icm:
        arbel_cmd_unmap_icm_aux ( arbel );
  err_map_icm_aux:
@@ -2304,7 +2343,7 @@ static int arbel_alloc_icm ( struct arbel *arbel,
  * @v arbel            Arbel device
  */
 static void arbel_free_icm ( struct arbel *arbel ) {
-       arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / 4096 ) );
+       arbel_cmd_unmap_icm ( arbel, ( arbel->icm_len / ARBEL_PAGE_SIZE ) );
        arbel_cmd_unmap_icm_aux ( arbel );
        ufree ( arbel->icm );
        arbel->icm = UNULL;
index dd64afb56ca0f12dc45506bb97affeec45f0637c..17803934cd47a91178b80f000f273c22384d0841 100644 (file)
@@ -93,6 +93,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #define ARBEL_PAGE_SIZE                        4096
 
+#define ARBEL_RDB_ENTRY_SIZE           32
+
 #define ARBEL_DB_POST_SND_OFFSET       0x10
 #define ARBEL_DB_EQ_OFFSET(_eqn)       ( 0x08 * (_eqn) )
 
@@ -103,6 +105,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
 
 #define ARBEL_EV_PORT_STATE_CHANGE     0x09
 
+#define ARBEL_LOG_MULTICAST_HASH_SIZE  3
+
 /*
  * Datatypes that seem to be missing from the autogenerated documentation
  *