|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.