Annotation of qemu/roms/ipxe/src/drivers/infiniband/arbel.h, revision 1.1.1.1

1.1       root        1: #ifndef _ARBEL_H
                      2: #define _ARBEL_H
                      3: 
                      4: /** @file
                      5:  *
                      6:  * Mellanox Arbel Infiniband HCA driver
                      7:  *
                      8:  */
                      9: 
                     10: FILE_LICENCE ( GPL2_OR_LATER );
                     11: 
                     12: #include <stdint.h>
                     13: #include <ipxe/uaccess.h>
                     14: #include <ipxe/ib_packet.h>
                     15: #include "mlx_bitops.h"
                     16: #include "MT25218_PRM.h"
                     17: 
                     18: /*
                     19:  * Hardware constants
                     20:  *
                     21:  */
                     22: 
                     23: /* Ports in existence */
                     24: #define ARBEL_NUM_PORTS                        2
                     25: #define ARBEL_PORT_BASE                        1
                     26: 
                     27: /* PCI BARs */
                     28: #define ARBEL_PCI_CONFIG_BAR           PCI_BASE_ADDRESS_0
                     29: #define ARBEL_PCI_CONFIG_BAR_SIZE      0x100000
                     30: #define ARBEL_PCI_UAR_BAR              PCI_BASE_ADDRESS_2
                     31: #define ARBEL_PCI_UAR_IDX              1
                     32: #define ARBEL_PCI_UAR_SIZE             0x1000
                     33: 
                     34: /* UAR context table (UCE) resource types */
                     35: #define ARBEL_UAR_RES_NONE             0x00
                     36: #define ARBEL_UAR_RES_CQ_CI            0x01
                     37: #define ARBEL_UAR_RES_CQ_ARM           0x02
                     38: #define ARBEL_UAR_RES_SQ               0x03
                     39: #define ARBEL_UAR_RES_RQ               0x04
                     40: #define ARBEL_UAR_RES_GROUP_SEP                0x07
                     41: 
                     42: /* Work queue entry and completion queue entry opcodes */
                     43: #define ARBEL_OPCODE_SEND              0x0a
                     44: #define ARBEL_OPCODE_RECV_ERROR                0xfe
                     45: #define ARBEL_OPCODE_SEND_ERROR                0xff
                     46: 
                     47: /* HCA command register opcodes */
                     48: #define ARBEL_HCR_QUERY_DEV_LIM                0x0003
                     49: #define ARBEL_HCR_QUERY_FW             0x0004
                     50: #define ARBEL_HCR_INIT_HCA             0x0007
                     51: #define ARBEL_HCR_CLOSE_HCA            0x0008
                     52: #define ARBEL_HCR_INIT_IB              0x0009
                     53: #define ARBEL_HCR_CLOSE_IB             0x000a
                     54: #define ARBEL_HCR_SW2HW_MPT            0x000d
                     55: #define ARBEL_HCR_MAP_EQ               0x0012
                     56: #define ARBEL_HCR_SW2HW_EQ             0x0013
                     57: #define ARBEL_HCR_HW2SW_EQ             0x0014
                     58: #define ARBEL_HCR_SW2HW_CQ             0x0016
                     59: #define ARBEL_HCR_HW2SW_CQ             0x0017
                     60: #define ARBEL_HCR_QUERY_CQ             0x0018
                     61: #define ARBEL_HCR_RST2INIT_QPEE                0x0019
                     62: #define ARBEL_HCR_INIT2RTR_QPEE                0x001a
                     63: #define ARBEL_HCR_RTR2RTS_QPEE         0x001b
                     64: #define ARBEL_HCR_RTS2RTS_QPEE         0x001c
                     65: #define ARBEL_HCR_2RST_QPEE            0x0021
                     66: #define ARBEL_HCR_QUERY_QPEE           0x0022
                     67: #define ARBEL_HCR_CONF_SPECIAL_QP      0x0023
                     68: #define ARBEL_HCR_MAD_IFC              0x0024
                     69: #define ARBEL_HCR_READ_MGM             0x0025
                     70: #define ARBEL_HCR_WRITE_MGM            0x0026
                     71: #define ARBEL_HCR_MGID_HASH            0x0027
                     72: #define ARBEL_HCR_RUN_FW               0x0ff6
                     73: #define ARBEL_HCR_DISABLE_LAM          0x0ff7
                     74: #define ARBEL_HCR_ENABLE_LAM           0x0ff8
                     75: #define ARBEL_HCR_UNMAP_ICM            0x0ff9
                     76: #define ARBEL_HCR_MAP_ICM              0x0ffa
                     77: #define ARBEL_HCR_UNMAP_ICM_AUX                0x0ffb
                     78: #define ARBEL_HCR_MAP_ICM_AUX          0x0ffc
                     79: #define ARBEL_HCR_SET_ICM_SIZE         0x0ffd
                     80: #define ARBEL_HCR_UNMAP_FA             0x0ffe
                     81: #define ARBEL_HCR_MAP_FA               0x0fff
                     82: 
                     83: /* Service types */
                     84: #define ARBEL_ST_UD                    0x03
                     85: #define ARBEL_ST_MLX                   0x07
                     86: 
                     87: /* MTUs */
                     88: #define ARBEL_MTU_2048                 0x04
                     89: 
                     90: #define ARBEL_NO_EQ                    64
                     91: 
                     92: #define ARBEL_INVALID_LKEY             0x00000100UL
                     93: 
                     94: #define ARBEL_PAGE_SIZE                        ( ( size_t ) 4096 )
                     95: 
                     96: #define ARBEL_RDB_ENTRY_SIZE           ( ( size_t ) 32 )
                     97: 
                     98: #define ARBEL_DB_POST_SND_OFFSET       0x10
                     99: #define ARBEL_DB_EQ_OFFSET(_eqn)       ( 0x08 * (_eqn) )
                    100: 
                    101: #define ARBEL_QPEE_OPT_PARAM_QKEY      0x00000020UL
                    102: 
                    103: #define ARBEL_MAP_EQ                   ( 0UL << 31 )
                    104: #define ARBEL_UNMAP_EQ                 ( 1UL << 31 )
                    105: 
                    106: #define ARBEL_EV_PORT_STATE_CHANGE     0x09
                    107: 
                    108: #define ARBEL_LOG_MULTICAST_HASH_SIZE  3
                    109: 
                    110: #define ARBEL_PM_STATE_ARMED           0x00
                    111: #define ARBEL_PM_STATE_REARM           0x01
                    112: #define ARBEL_PM_STATE_MIGRATED                0x03
                    113: 
                    114: /*
                    115:  * Datatypes that seem to be missing from the autogenerated documentation
                    116:  *
                    117:  */
                    118: struct arbelprm_mgm_hash_st {
                    119:        pseudo_bit_t reserved0[0x00020];
                    120: /* -------------- */
                    121:        pseudo_bit_t hash[0x00010];
                    122:        pseudo_bit_t reserved1[0x00010];
                    123: } __attribute__ (( packed ));
                    124: 
                    125: struct arbelprm_scalar_parameter_st {
                    126:        pseudo_bit_t reserved0[0x00020];
                    127: /* -------------- */
                    128:        pseudo_bit_t value[0x00020];
                    129: } __attribute__ (( packed ));
                    130: 
                    131: struct arbelprm_event_mask_st {
                    132:        pseudo_bit_t reserved0[0x00020];
                    133: /* -------------- */
                    134:        pseudo_bit_t completion[0x00001];
                    135:        pseudo_bit_t path_migration_succeeded[0x00001];
                    136:        pseudo_bit_t communication_established[0x00001];
                    137:        pseudo_bit_t send_queue_drained[0x00001];
                    138:        pseudo_bit_t cq_error[0x00001];
                    139:        pseudo_bit_t wq_catastrophe[0x00001];
                    140:        pseudo_bit_t qpc_catastrophe[0x00001];
                    141:        pseudo_bit_t path_migration_failed[0x00001];
                    142:        pseudo_bit_t reserved1[0x00001];
                    143:        pseudo_bit_t port_state_change[0x00001];
                    144:        pseudo_bit_t command_done[0x00001];
                    145:        pseudo_bit_t reserved2[0x00005];
                    146:        pseudo_bit_t wq_invalid_request[0x00001];
                    147:        pseudo_bit_t wq_access_violation[0x00001];
                    148:        pseudo_bit_t srq_catastrophe[0x00001];
                    149:        pseudo_bit_t srq_last_wqe[0x00001];
                    150:        pseudo_bit_t srq_rq_limit[0x00001];
                    151:        pseudo_bit_t gpio[0x00001];
                    152:        pseudo_bit_t clientreregister[0x00001];
                    153:        pseudo_bit_t path_migration_armed[0x00001];
                    154:        pseudo_bit_t reserved3[0x00008];
                    155: } __attribute__ (( packed ));
                    156: 
                    157: struct arbelprm_eq_set_ci_st {
                    158:        pseudo_bit_t ci[0x00020];
                    159: } __attribute__ (( packed ));
                    160: 
                    161: struct arbelprm_port_state_change_event_st {
                    162:        pseudo_bit_t reserved[0x00020];
                    163:        struct arbelprm_port_state_change_st data;
                    164: } __attribute__ (( packed ));
                    165: 
                    166: /*
                    167:  * Wrapper structures for hardware datatypes
                    168:  *
                    169:  */
                    170: 
                    171: struct MLX_DECLARE_STRUCT ( arbelprm_access_lam );
                    172: struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_context );
                    173: struct MLX_DECLARE_STRUCT ( arbelprm_completion_queue_entry );
                    174: struct MLX_DECLARE_STRUCT ( arbelprm_completion_with_error );
                    175: struct MLX_DECLARE_STRUCT ( arbelprm_cq_arm_db_record );
                    176: struct MLX_DECLARE_STRUCT ( arbelprm_cq_ci_db_record );
                    177: struct MLX_DECLARE_STRUCT ( arbelprm_event_mask );
                    178: struct MLX_DECLARE_STRUCT ( arbelprm_event_queue_entry );
                    179: struct MLX_DECLARE_STRUCT ( arbelprm_eq_set_ci );
                    180: struct MLX_DECLARE_STRUCT ( arbelprm_eqc );
                    181: struct MLX_DECLARE_STRUCT ( arbelprm_hca_command_register );
                    182: struct MLX_DECLARE_STRUCT ( arbelprm_init_hca );
                    183: struct MLX_DECLARE_STRUCT ( arbelprm_init_ib );
                    184: struct MLX_DECLARE_STRUCT ( arbelprm_mad_ifc );
                    185: struct MLX_DECLARE_STRUCT ( arbelprm_mgm_entry );
                    186: struct MLX_DECLARE_STRUCT ( arbelprm_mgm_hash );
                    187: struct MLX_DECLARE_STRUCT ( arbelprm_mpt );
                    188: struct MLX_DECLARE_STRUCT ( arbelprm_port_state_change_event );
                    189: struct MLX_DECLARE_STRUCT ( arbelprm_qp_db_record );
                    190: struct MLX_DECLARE_STRUCT ( arbelprm_qp_ee_state_transitions );
                    191: struct MLX_DECLARE_STRUCT ( arbelprm_query_dev_lim );
                    192: struct MLX_DECLARE_STRUCT ( arbelprm_query_fw );
                    193: struct MLX_DECLARE_STRUCT ( arbelprm_queue_pair_ee_context_entry );
                    194: struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
                    195: struct MLX_DECLARE_STRUCT ( arbelprm_scalar_parameter );
                    196: struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
                    197: struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
                    198: struct MLX_DECLARE_STRUCT ( arbelprm_virtual_physical_mapping );
                    199: struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_mlx );
                    200: struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
                    201: struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
                    202: struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
                    203: struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ud );
                    204: 
                    205: /*
                    206:  * Composite hardware datatypes
                    207:  *
                    208:  */
                    209: 
                    210: #define ARBEL_MAX_GATHER 2
                    211: 
                    212: struct arbelprm_ud_send_wqe {
                    213:        struct arbelprm_wqe_segment_next next;
                    214:        struct arbelprm_wqe_segment_ctrl_send ctrl;
                    215:        struct arbelprm_wqe_segment_ud ud;
                    216:        struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER];
                    217: } __attribute__ (( packed ));
                    218: 
                    219: struct arbelprm_mlx_send_wqe {
                    220:        struct arbelprm_wqe_segment_next next;
                    221:        struct arbelprm_wqe_segment_ctrl_mlx ctrl;
                    222:        struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_GATHER];
                    223:        uint8_t headers[IB_MAX_HEADER_SIZE];
                    224: } __attribute__ (( packed ));
                    225: 
                    226: #define ARBEL_MAX_SCATTER 1
                    227: 
                    228: struct arbelprm_recv_wqe {
                    229:        /* The autogenerated header is inconsistent between send and
                    230:         * receive WQEs.  The "ctrl" structure for receive WQEs is
                    231:         * defined to include the "next" structure.  Since the "ctrl"
                    232:         * part of the "ctrl" structure contains only "reserved, must
                    233:         * be zero" bits, we ignore its definition and provide
                    234:         * something more usable.
                    235:         */
                    236:        struct arbelprm_recv_wqe_segment_next next;
                    237:        uint32_t ctrl[2]; /* All "reserved, must be zero" */
                    238:        struct arbelprm_wqe_segment_data_ptr data[ARBEL_MAX_SCATTER];
                    239: } __attribute__ (( packed ));
                    240: 
                    241: union arbelprm_completion_entry {
                    242:        struct arbelprm_completion_queue_entry normal;
                    243:        struct arbelprm_completion_with_error error;
                    244: } __attribute__ (( packed ));
                    245: 
                    246: union arbelprm_event_entry {
                    247:        struct arbelprm_event_queue_entry generic;
                    248:        struct arbelprm_port_state_change_event port_state_change;
                    249: } __attribute__ (( packed ));
                    250: 
                    251: union arbelprm_doorbell_record {
                    252:        struct arbelprm_cq_arm_db_record cq_arm;
                    253:        struct arbelprm_cq_ci_db_record cq_ci;
                    254:        struct arbelprm_qp_db_record qp;
                    255: } __attribute__ (( packed ));
                    256: 
                    257: union arbelprm_doorbell_register {
                    258:        struct arbelprm_send_doorbell send;
                    259:        uint32_t dword[2];
                    260: } __attribute__ (( packed ));
                    261: 
                    262: union arbelprm_eq_doorbell_register {
                    263:        struct arbelprm_eq_set_ci ci;
                    264:        uint32_t dword[1];
                    265: } __attribute__ (( packed ));
                    266: 
                    267: union arbelprm_mad {
                    268:        struct arbelprm_mad_ifc ifc;
                    269:        union ib_mad mad;
                    270: } __attribute__ (( packed ));
                    271: 
                    272: /*
                    273:  * iPXE-specific definitions
                    274:  *
                    275:  */
                    276: 
                    277: /** Arbel device limits */
                    278: struct arbel_dev_limits {
                    279:        /** Number of reserved QPs */
                    280:        unsigned int reserved_qps;
                    281:        /** QP context entry size */
                    282:        size_t qpc_entry_size;
                    283:        /** Extended QP context entry size */
                    284:        size_t eqpc_entry_size;
                    285:        /** Number of reserved SRQs */
                    286:        unsigned int reserved_srqs;
                    287:        /** SRQ context entry size */
                    288:        size_t srqc_entry_size;
                    289:        /** Number of reserved EEs */
                    290:        unsigned int reserved_ees;
                    291:        /** EE context entry size */
                    292:        size_t eec_entry_size;
                    293:        /** Extended EE context entry size */
                    294:        size_t eeec_entry_size;
                    295:        /** Number of reserved CQs */
                    296:        unsigned int reserved_cqs;
                    297:        /** CQ context entry size */
                    298:        size_t cqc_entry_size;
                    299:        /** Number of reserved EQs */
                    300:        unsigned int reserved_eqs;
                    301:        /** Number of reserved MTTs */
                    302:        unsigned int reserved_mtts;
                    303:        /** MTT entry size */
                    304:        size_t mtt_entry_size;
                    305:        /** Number of reserved MRWs */
                    306:        unsigned int reserved_mrws;
                    307:        /** MPT entry size */
                    308:        size_t mpt_entry_size;
                    309:        /** Number of reserved RDBs */
                    310:        unsigned int reserved_rdbs;
                    311:        /** EQ context entry size */
                    312:        size_t eqc_entry_size;
                    313:        /** Number of reserved UARs */
                    314:        unsigned int reserved_uars;
                    315:        /** UAR scratchpad entry size */
                    316:        size_t uar_scratch_entry_size;
                    317: };
                    318: 
                    319: /** Alignment of Arbel send work queue entries */
                    320: #define ARBEL_SEND_WQE_ALIGN 128
                    321: 
                    322: /** An Arbel send work queue entry */
                    323: union arbel_send_wqe {
                    324:        struct arbelprm_wqe_segment_next next;
                    325:        struct arbelprm_ud_send_wqe ud;
                    326:        struct arbelprm_mlx_send_wqe mlx;
                    327:        uint8_t force_align[ARBEL_SEND_WQE_ALIGN];
                    328: } __attribute__ (( packed ));
                    329: 
                    330: /** An Arbel send work queue */
                    331: struct arbel_send_work_queue {
                    332:        /** Doorbell record number */
                    333:        unsigned int doorbell_idx;
                    334:        /** Work queue entries */
                    335:        union arbel_send_wqe *wqe;
                    336:        /** Size of work queue */
                    337:        size_t wqe_size;
                    338: };
                    339: 
                    340: /** Alignment of Arbel receive work queue entries */
                    341: #define ARBEL_RECV_WQE_ALIGN 64
                    342: 
                    343: /** An Arbel receive work queue entry */
                    344: union arbel_recv_wqe {
                    345:        struct arbelprm_recv_wqe recv;
                    346:        uint8_t force_align[ARBEL_RECV_WQE_ALIGN];
                    347: } __attribute__ (( packed ));
                    348: 
                    349: /** An Arbel receive work queue */
                    350: struct arbel_recv_work_queue {
                    351:        /** Doorbell record number */
                    352:        unsigned int doorbell_idx;
                    353:        /** Work queue entries */
                    354:        union arbel_recv_wqe *wqe;
                    355:        /** Size of work queue */
                    356:        size_t wqe_size;
                    357: };
                    358: 
                    359: /** Number of special queue pairs */
                    360: #define ARBEL_NUM_SPECIAL_QPS 4
                    361: 
                    362: /** Number of queue pairs reserved for the "special QP" block
                    363:  *
                    364:  * The special QPs must be in (2n,2n+1) pairs, hence we need to
                    365:  * reserve one extra QP to allow for alignment.
                    366:  */
                    367: #define ARBEL_RSVD_SPECIAL_QPS ( ARBEL_NUM_SPECIAL_QPS + 1 )
                    368: 
                    369: /** Maximum number of allocatable queue pairs
                    370:  *
                    371:  * This is a policy decision, not a device limit.
                    372:  */
                    373: #define ARBEL_MAX_QPS          8
                    374: 
                    375: /** Queue pair number randomisation mask */
                    376: #define ARBEL_QPN_RANDOM_MASK 0xfff000
                    377: 
                    378: /** Arbel queue pair state */
                    379: enum arbel_queue_pair_state {
                    380:        ARBEL_QP_ST_RST = 0,
                    381:        ARBEL_QP_ST_INIT,
                    382:        ARBEL_QP_ST_RTR,
                    383:        ARBEL_QP_ST_RTS,
                    384: };
                    385: 
                    386: /** An Arbel queue pair */
                    387: struct arbel_queue_pair {
                    388:        /** Send work queue */
                    389:        struct arbel_send_work_queue send;
                    390:        /** Receive work queue */
                    391:        struct arbel_recv_work_queue recv;
                    392:        /** Queue state */
                    393:        enum arbel_queue_pair_state state;
                    394: };
                    395: 
                    396: /** Maximum number of allocatable completion queues
                    397:  *
                    398:  * This is a policy decision, not a device limit.
                    399:  */
                    400: #define ARBEL_MAX_CQS          8
                    401: 
                    402: /** An Arbel completion queue */
                    403: struct arbel_completion_queue {
                    404:        /** Consumer counter doorbell record number */
                    405:        unsigned int ci_doorbell_idx;
                    406:        /** Arm queue doorbell record number */
                    407:        unsigned int arm_doorbell_idx;
                    408:        /** Completion queue entries */
                    409:        union arbelprm_completion_entry *cqe;
                    410:        /** Size of completion queue */
                    411:        size_t cqe_size;
                    412: };
                    413: 
                    414: /** Maximum number of allocatable event queues
                    415:  *
                    416:  * This is a policy decision, not a device limit.
                    417:  */
                    418: #define ARBEL_MAX_EQS          64
                    419: 
                    420: /** A Arbel event queue */
                    421: struct arbel_event_queue {
                    422:        /** Event queue entries */
                    423:        union arbelprm_event_entry *eqe;
                    424:        /** Size of event queue */
                    425:        size_t eqe_size;
                    426:        /** Event queue number */
                    427:        unsigned long eqn;
                    428:        /** Next event queue entry index */
                    429:        unsigned long next_idx;
                    430:        /** Doorbell register */
                    431:        void *doorbell;
                    432: };
                    433: 
                    434: /** Number of event queue entries
                    435:  *
                    436:  * This is a policy decision.
                    437:  */
                    438: #define ARBEL_NUM_EQES         4
                    439: 
                    440: 
                    441: /** An Arbel resource bitmask */
                    442: typedef uint32_t arbel_bitmask_t;
                    443: 
                    444: /** Size of an Arbel resource bitmask */
                    445: #define ARBEL_BITMASK_SIZE(max_entries)                                             \
                    446:        ( ( (max_entries) + ( 8 * sizeof ( arbel_bitmask_t ) ) - 1 ) /       \
                    447:          ( 8 * sizeof ( arbel_bitmask_t ) ) )
                    448: 
                    449: /** An Arbel device */
                    450: struct arbel {
                    451:        /** PCI configuration registers */
                    452:        void *config;
                    453:        /** PCI user Access Region */
                    454:        void *uar;
                    455:        /** Event queue consumer index doorbells */
                    456:        void *eq_ci_doorbells;
                    457: 
                    458:        /** Command input mailbox */
                    459:        void *mailbox_in;
                    460:        /** Command output mailbox */
                    461:        void *mailbox_out;
                    462: 
                    463:        /** Firmware area in external memory */
                    464:        userptr_t firmware_area;
                    465:        /** ICM size */
                    466:        size_t icm_len;
                    467:        /** ICM AUX size */
                    468:        size_t icm_aux_len;
                    469:        /** ICM area */
                    470:        userptr_t icm;
                    471:        /** Offset within ICM of doorbell records */
                    472:        size_t db_rec_offset;
                    473:        /** Doorbell records */
                    474:        union arbelprm_doorbell_record *db_rec;
                    475:        /** Event queue */
                    476:        struct arbel_event_queue eq;
                    477:        /** Unrestricted LKey
                    478:         *
                    479:         * Used to get unrestricted memory access.
                    480:         */
                    481:        unsigned long lkey;
                    482: 
                    483:        /** Completion queue in-use bitmask */
                    484:        arbel_bitmask_t cq_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_CQS ) ];
                    485:        /** Queue pair in-use bitmask */
                    486:        arbel_bitmask_t qp_inuse[ ARBEL_BITMASK_SIZE ( ARBEL_MAX_QPS ) ];
                    487:        
                    488:        /** Device limits */
                    489:        struct arbel_dev_limits limits;
                    490:        /** Special QPN base */
                    491:        unsigned long special_qpn_base;
                    492:        /** QPN base */
                    493:        unsigned long qpn_base;
                    494: 
                    495:        /** Infiniband devices */
                    496:        struct ib_device *ibdev[ARBEL_NUM_PORTS];
                    497: };
                    498: 
                    499: /** Global protection domain */
                    500: #define ARBEL_GLOBAL_PD                        0x123456
                    501: 
                    502: /** Memory key prefix */
                    503: #define ARBEL_MKEY_PREFIX              0x77000000UL
                    504: 
                    505: /*
                    506:  * HCA commands
                    507:  *
                    508:  */
                    509: 
                    510: #define ARBEL_HCR_BASE                 0x80680
                    511: #define ARBEL_HCR_REG(x)               ( ARBEL_HCR_BASE + 4 * (x) )
                    512: #define ARBEL_HCR_MAX_WAIT_MS          2000
                    513: #define ARBEL_MBOX_ALIGN               4096
                    514: #define ARBEL_MBOX_SIZE                        512
                    515: 
                    516: /* HCA command is split into
                    517:  *
                    518:  * bits  11:0  Opcode
                    519:  * bit     12  Input uses mailbox
                    520:  * bit     13  Output uses mailbox
                    521:  * bits 22:14  Input parameter length (in dwords)
                    522:  * bits 31:23  Output parameter length (in dwords)
                    523:  *
                    524:  * Encoding the information in this way allows us to cut out several
                    525:  * parameters to the arbel_command() call.
                    526:  */
                    527: #define ARBEL_HCR_IN_MBOX              0x00001000UL
                    528: #define ARBEL_HCR_OUT_MBOX             0x00002000UL
                    529: #define ARBEL_HCR_OPCODE( _command )   ( (_command) & 0xfff )
                    530: #define ARBEL_HCR_IN_LEN( _command )   ( ( (_command) >> 12 ) & 0x7fc )
                    531: #define ARBEL_HCR_OUT_LEN( _command )  ( ( (_command) >> 21 ) & 0x7fc )
                    532: 
                    533: /** Build HCR command from component parts */
                    534: #define ARBEL_HCR_INOUT_CMD( _opcode, _in_mbox, _in_len,                    \
                    535:                             _out_mbox, _out_len )                           \
                    536:        ( (_opcode) |                                                        \
                    537:          ( (_in_mbox) ? ARBEL_HCR_IN_MBOX : 0 ) |                           \
                    538:          ( ( (_in_len) / 4 ) << 14 ) |                                      \
                    539:          ( (_out_mbox) ? ARBEL_HCR_OUT_MBOX : 0 ) |                         \
                    540:          ( ( (_out_len) / 4 ) << 23 ) )
                    541: 
                    542: #define ARBEL_HCR_IN_CMD( _opcode, _in_mbox, _in_len )                      \
                    543:        ARBEL_HCR_INOUT_CMD ( _opcode, _in_mbox, _in_len, 0, 0 )
                    544: 
                    545: #define ARBEL_HCR_OUT_CMD( _opcode, _out_mbox, _out_len )                   \
                    546:        ARBEL_HCR_INOUT_CMD ( _opcode, 0, 0, _out_mbox, _out_len )
                    547: 
                    548: #define ARBEL_HCR_VOID_CMD( _opcode )                                       \
                    549:        ARBEL_HCR_INOUT_CMD ( _opcode, 0, 0, 0, 0 )
                    550: 
                    551: /*
                    552:  * Doorbell record allocation
                    553:  *
                    554:  * The doorbell record map looks like:
                    555:  *
                    556:  *    ARBEL_MAX_CQS * Arm completion queue doorbell
                    557:  *    ARBEL_MAX_QPS * Send work request doorbell
                    558:  *    Group separator
                    559:  *    ...(empty space)...
                    560:  *    ARBEL_MAX_QPS * Receive work request doorbell
                    561:  *    ARBEL_MAX_CQS * Completion queue consumer counter update doorbell
                    562:  */
                    563: 
                    564: #define ARBEL_MAX_DOORBELL_RECORDS 512
                    565: #define ARBEL_GROUP_SEPARATOR_DOORBELL \
                    566:        ( ARBEL_MAX_CQS + ARBEL_RSVD_SPECIAL_QPS + ARBEL_MAX_QPS )
                    567: 
                    568: /**
                    569:  * Get arm completion queue doorbell index
                    570:  *
                    571:  * @v arbel            Arbel device
                    572:  * @v cq               Completion queue
                    573:  * @ret doorbell_idx   Doorbell index
                    574:  */
                    575: static inline unsigned int
                    576: arbel_cq_arm_doorbell_idx ( struct arbel *arbel,
                    577:                            struct ib_completion_queue *cq ) {
                    578:        return ( cq->cqn - arbel->limits.reserved_cqs );
                    579: }
                    580: 
                    581: /**
                    582:  * Get send work request doorbell index
                    583:  *
                    584:  * @v arbel            Arbel device
                    585:  * @v qp               Queue pair
                    586:  * @ret doorbell_idx   Doorbell index
                    587:  */
                    588: static inline unsigned int
                    589: arbel_send_doorbell_idx ( struct arbel *arbel, struct ib_queue_pair *qp ) {
                    590:        return ( ARBEL_MAX_CQS +
                    591:                 ( ( qp->qpn & ~ARBEL_QPN_RANDOM_MASK ) -
                    592:                   arbel->special_qpn_base ) );
                    593: }
                    594: 
                    595: /**
                    596:  * Get receive work request doorbell index
                    597:  *
                    598:  * @v arbel            Arbel device
                    599:  * @v qp               Queue pair
                    600:  * @ret doorbell_idx   Doorbell index
                    601:  */
                    602: static inline unsigned int
                    603: arbel_recv_doorbell_idx ( struct arbel *arbel, struct ib_queue_pair *qp ) {
                    604:        return ( ARBEL_MAX_DOORBELL_RECORDS - ARBEL_MAX_CQS -
                    605:                 ( ( qp->qpn & ~ARBEL_QPN_RANDOM_MASK ) -
                    606:                   arbel->special_qpn_base ) - 1 );
                    607: }
                    608: 
                    609: /**
                    610:  * Get completion queue consumer counter doorbell index
                    611:  *
                    612:  * @v arbel            Arbel device
                    613:  * @v cq               Completion queue
                    614:  * @ret doorbell_idx   Doorbell index
                    615:  */
                    616: static inline unsigned int
                    617: arbel_cq_ci_doorbell_idx ( struct arbel *arbel,
                    618:                           struct ib_completion_queue *cq ) {
                    619:        return ( ARBEL_MAX_DOORBELL_RECORDS -
                    620:                 ( cq->cqn - arbel->limits.reserved_cqs ) - 1 );
                    621: }
                    622: 
                    623: #endif /* _ARBEL_H */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.