#ifndef __mt25218_h__ #define __mt25218_h__ #include "MT25218_PRM.h" #include "ib_mad.h" #define TAVOR_DEVICE_ID 0x5a44 #define TAVOR_BRIDGE_DEVICE_ID 0x5a46 #define ARTAVOR_DEVICE_ID 0x6278 #define MEMFREE_RESET_OFFSET 0xF0010 #define INVALID_WQE_LKEY 0x00000100 /* * memfree specific command * */ #define MEMFREE_CMD_QUERY_ADAPTER 0x006 #define MEMFREE_CMD_WRITE_MGM 0x026 #define MEMFREE_CMD_MOD_STAT_CFG 0x034 #define MEMFREE_CMD_QUERY_FW 0x004 #define MEMFREE_CMD_ENABLE_LAM 0xff8 #define MEMFREE_CMD_MAP_FA 0xfff #define MEMFREE_CMD_UNMAP_FA 0xffe #define MEMFREE_CMD_RUN_FW 0xff6 #define MEMFREE_CMD_SET_ICM_SIZE 0xffd #define MEMFREE_CMD_MAP_ICM_AUX 0xffc #define MEMFREE_CMD_MAP_ICM 0xffa #define MEMFREE_CMD_QUERY_DEV_LIM 0x003 /* * Tavor specific event types * Only event types that are specific to Tavor * and are used by the driver are listed here */ #define TAVOR_IF_EV_TYPE_OVERRUN 0x0F /* * EQ doorbel commands */ #define EQ_DBELL_CMD_INC_CONS_IDX 1 /* increment Consumer_indx by one */ #define EQ_DBELL_CMD_ARM_EQ 2 /* Request notifcation for next event (Arm EQ) */ #define EQ_DBELL_CMD_DISARM_CQ 3 /* Disarm CQ (CQ number is specified in EQ_param) */ #define EQ_DBELL_CMD_SET_CONS_IDX 4 /* set Consumer_indx to value of EQ_param */ #define EQ_DBELL_CMD_ALWAYS_ARM 5 /* move EQ to Always Armed state */ /* * CQ doorbel commands */ #define CQ_DBELL_CMD_INC_CONS_IDX 1 #define CQ_DBELL_CMD_REQ_NOTIF_SOL_UNSOL 2 #define CQ_DBELL_CMD_REQ_NOTIF_SOL 3 #define CQ_DBELL_CMD_SET_CONS_IDX 4 #define CQ_DBELL_CMD_REQ_NOTIF_MULT 5 #define INPRM_BUF_SZ 4096 #define INPRM_BUF_ALIGN 4096 #define OUTPRM_BUF_SZ 4096 #define OUTPRM_BUF_ALIGN 4096 /* * sizes of parameter blocks used in certain * commands. * TODO: replace them with sizeof * operators of the appropriate structs */ #define SW2HW_MPT_IBUF_SZ MT_STRUCT_SIZE(arbelprm_mpt_st) #define SW2HW_EQ_IBUF_SZ MT_STRUCT_SIZE(arbelprm_eqc_st) #define INIT_IB_IBUF_SZ MT_STRUCT_SIZE(arbelprm_init_ib_st) #define SW2HW_CQ_IBUF_SZ MT_STRUCT_SIZE(arbelprm_completion_queue_context_st) #define QPCTX_IBUF_SZ MT_STRUCT_SIZE(arbelprm_queue_pair_ee_context_entry_st) #define EQN 0 #define UAR_IDX 1 #define QPC_OFFSET 0 #define CQC_OFFSET (QPC_OFFSET + 0x100000) #define EQPC_OFFSET (CQC_OFFSET + 0x100000) #define EQC_OFFSET (EQPC_OFFSET + 0x100000) #define MC_BASE_OFFSET (EQC_OFFSET + 0x100000) #define MPT_BASE_OFFSET (MC_BASE_OFFSET + 0x100000) #define MTT_BASE_OFFSET (MPT_BASE_OFFSET + 0x100000) #define LOG2_QPS 7 #define LOG2_CQS 8 #define LOG2_EQS 6 #define LOG2_MC_ENTRY 6 /* 8 QPs per group */ #define LOG2_MC_GROUPS 3 /* 8 groups */ #define LOG2_MPT_ENTRIES 5 #define LOG2_EQ_SZ 5 #define LOG2_CQ_SZ 5 #define NUM_PORTS 2 #define EQE_OWNER_OFFSET 31 #define EQE_OWNER_VAL_HW 0x80 #define CQE_OWNER_OFFSET 31 #define CQE_OWNER_VAL_HW 0x80 #define POST_RCV_OFFSET 0x18 #define POST_SND_OFFSET 0x10 #define CQ_DBELL_OFFSET 0x20 #define EQ_DBELL_OFFSET 0x28 #define CQE_ERROR_OPCODE 0xfe #define OWNER_HW 1 #define OWNER_SW 0 #define MAX_GATHER 1 /* max gather entries used in send */ #define MAX_SCATTER 2 #define LOG2_MADS_SND_CQ_SZ LOG2_CQ_SZ #define LOG2_MADS_RCV_CQ_SZ LOG2_CQ_SZ #define LOG2_IPOIB_SND_CQ_SZ LOG2_CQ_SZ #define LOG2_IPOIB_RCV_CQ_SZ LOG2_CQ_SZ #define NUM_MADS_SND_CQES (1< NUM_IPOIB_RCV_WQES #define MAX_RCV_WQES NUM_MADS_RCV_WQES #else #define MAX_RCV_WQES NUM_IPOIB_RCV_WQES #endif #define NUM_MADS_SND_WQES (1<<1) #define NUM_IPOIB_SND_WQES (1<<1) #if NUM_MADS_SND_WQES > NUM_IPOIB_SND_WQES #define MAX_SND_WQES NUM_MADS_SND_WQES #else #define MAX_SND_WQES NUM_IPOIB_SND_WQES #endif /* uar context indexes */ enum { MADS_RCV_CQ_ARM_DB_IDX, MADS_SND_CQ_ARM_DB_IDX, IPOIB_RCV_CQ_ARM_DB_IDX, IPOIB_SND_CQ_ARM_DB_IDX, MADS_SND_QP_DB_IDX, IPOIB_SND_QP_DB_IDX, GROUP_SEP_IDX, START_UNMAPPED_DB_IDX, /* -------------------------- unmapped doorbell records -------------------------- */ END_UNMAPPED_DB_IDX = 505, MADS_RCV_QP_DB_IDX = 506, IPOIB_RCV_QP_DB_IDX = 507, MADS_RCV_CQ_CI_DB_IDX = 508, MADS_SND_CQ_CI_DB_IDX = 509, IPOIB_RCV_CQ_CI_DB_IDX = 510, IPOIB_SND_CQ_CI_DB_IDX = 511 }; /* uar resources types */ enum { UAR_RES_INVALID = 0x0, /* Invalid (not allocated) DoorBell record */ UAR_RES_CQ_SET_CI = 0x1, /* CQ SET_CI DoorBell record */ UAR_RES_CQ_ARM = 0x2, /* CQ ARM DoorBell record */ UAR_RES_SQ_DBELL = 0x3, /* Send Queue DoorBell record */ UAR_RES_RQ_DBELL = 0x4, /* Receive Queue DoorBell record */ UAR_RES_SRQ_DBELL = 0x5, /* Shared Receive Queue DoorBell record */ UAR_RES_GROUP_SEP = 0x7 /* Group Separator record */ }; enum { TS_RC, TS_UC, TS_RD, TS_UD, TS_MLX }; enum { PM_STATE_ARMED = 0, PM_STATE_REARM = 1, PM_STATE_MIGRATED = 3 }; enum { DOORBEL_RES_SQ = 3, DOORBEL_RES_RQ = 4, DOORBEL_RES_SRQ = 5 }; struct ib_buffers_st { __u8 send_mad_buf[NUM_MADS_SND_WQES][MAD_BUF_SZ]; __u8 rcv_mad_buf[NUM_MADS_RCV_WQES][MAD_BUF_SZ + GRH_SIZE]; __u8 ipoib_rcv_buf[NUM_IPOIB_RCV_WQES][IPOIB_RCV_BUF_SZ + GRH_SIZE]; __u8 ipoib_rcv_grh_buf[NUM_IPOIB_RCV_WQES][IPOIB_RCV_BUF_SZ]; __u8 send_ipoib_buf[NUM_IPOIB_SND_WQES][IPOIB_SND_BUF_SZ]; }; struct pcidev { unsigned long bar[6]; __u32 dev_config_space[64]; struct pci_device *dev; __u8 bus; __u8 devfn; }; struct dev_pci_struct { struct pcidev dev; struct pcidev br; void *cr_space; void *uar; }; struct eq_st { __u8 eqn; __u32 cons_counter; __u32 eq_size; void *ci_base_base_addr; struct eqe_t *eq_buf; }; struct eqe_t { __u8 raw[MT_STRUCT_SIZE(arbelprm_event_queue_entry_st)]; } __attribute__ ((packed)); enum qp_state_e { QP_STATE_RST = 0, QP_STATE_INIT = 1, QP_STATE_RTR = 2, QP_STATE_RTS = 3, QP_STATE_SQEr = 4, QP_STATE_SQD = 5, QP_STATE_ERR = 6, QP_STATE_SQDING = 7, QP_STATE_SUSPEND = 9 }; struct memory_pointer_st { __u32 byte_count; __u32 lkey; __u32 local_addr_h; __u32 local_addr_l; } __attribute__ ((packed)); /* receive wqe descriptor */ struct recv_wqe_st { /* part referenced by hardware */ __u8 control[MT_STRUCT_SIZE(arbelprm_wqe_segment_ctrl_recv_st)]; struct memory_pointer_st mpointer[MAX_SCATTER]; } __attribute__ ((packed)); struct recv_wqe_cont_st { struct recv_wqe_st wqe; struct udqp_st *qp; /* qp this wqe is used with */ } __attribute__ ((packed)); #define RECV_WQE_U_ALIGN 64 union recv_wqe_u { __u8 align[RECV_WQE_U_ALIGN]; /* this ensures proper alignment */ struct recv_wqe_st wqe; struct recv_wqe_cont_st wqe_cont; } __attribute__ ((packed)); struct send_doorbell_st { __u8 raw[MT_STRUCT_SIZE(arbelprm_send_doorbell_st)]; } __attribute__ ((packed)); struct next_control_seg_st { __u8 next[MT_STRUCT_SIZE(arbelprm_wqe_segment_next_st)]; __u8 control[MT_STRUCT_SIZE(arbelprm_wqe_segment_ctrl_send_st)]; } __attribute__ ((packed)); struct ud_seg_st { __u8 av[MT_STRUCT_SIZE(arbelprm_wqe_segment_ud_st)]; } __attribute__ ((packed)); struct ud_send_wqe_st { struct next_control_seg_st next; /* 16 bytes */ struct ud_seg_st udseg; /* 48 bytes */ struct memory_pointer_st mpointer[MAX_GATHER]; /* 16 * MAX_GATHER bytes */ } __attribute__ ((packed)); struct ude_send_wqe_cont_st { struct ud_send_wqe_st wqe; struct udqp_st *qp; /* qp this wqe is used with */ } __attribute__ ((packed)); #define UD_SEND_WQE_U_ALIGN 128 union ud_send_wqe_u { __u8 align[UD_SEND_WQE_U_ALIGN]; struct ude_send_wqe_cont_st wqe_cont; } __attribute__ ((packed)); struct address_vector_st { __u8 raw[MT_STRUCT_SIZE(arbelprm_ud_address_vector_st)]; } __attribute__ ((packed)); struct ud_av_st { struct address_vector_st av; __u32 dest_qp; /* destination qpn */ __u32 qkey; __u8 next_free; } __attribute__ ((packed)); union ud_av_u { struct ud_av_st ud_av; } __attribute__ ((packed)); struct udav_st { union ud_av_u av_array[NUM_AVS]; __u8 udav_next_free; }; union cqe_st { __u8 good_cqe[MT_STRUCT_SIZE(arbelprm_completion_queue_entry_st)]; __u8 error_cqe[MT_STRUCT_SIZE(arbelprm_completion_with_error_st)]; } __attribute__ ((packed)); struct qp_ee_ctx_t { __u8 raw[MT_STRUCT_SIZE(arbelprm_queue_pair_ee_context_entry_st)]; } __attribute__ ((packed)); struct qp_ee_state_tarnisition_st { __u32 opt_param_mask; __u32 r1; struct qp_ee_ctx_t ctx; __u32 r2[62]; } __attribute__ ((packed)); struct cq_dbell_st { __u8 raw[MT_STRUCT_SIZE(arbelprm_cq_cmd_doorbell_st)]; } __attribute__ ((packed)); struct mad_ifc_inprm_st { union mad_u mad; } __attribute__ ((packed)); struct wqe_buf_st { struct ud_send_wqe_st *sndq; struct recv_wqe_st *rcvq; }; struct mad_buffer_st { void *buf; /* pointer to a 256 byte buffer */ __u8 owner; /* sw or hw ownership BUF_OWNER_SW or BUF_OWNER_HW */ }; struct rcv_buf_st { void *buf; __u8 busy; }; struct ib_eqe_st { __u8 event_type; __u32 cqn; }; struct cq_st { __u32 cqn; union cqe_st *cq_buf; __u32 cons_counter; /* consuner counter */ __u8 num_cqes; __u32 arm_db_ctx_idx; void *arm_db_ctx_pointer; __u32 ci_db_ctx_idx; void *ci_db_ctx_pointer; }; struct udqp_st { /* cq used by this QP */ struct cq_st snd_cq; struct cq_st rcv_cq; /* QP related data */ __u32 qpn; /* QP number */ __u32 qkey; __u8 recv_wqe_cur_free; __u8 recv_wqe_alloc_idx; __u8 max_recv_wqes; void *rcv_bufs[MAX_RCV_WQES]; union recv_wqe_u *rcv_wq; /* receive work queue */ struct recv_wqe_st *last_posted_rcv_wqe; __u8 snd_wqe_cur_free; __u8 snd_wqe_alloc_idx; __u8 max_snd_wqes; void *snd_bufs[MAX_SND_WQES]; __u16 send_buf_sz; __u16 rcv_buf_sz; union ud_send_wqe_u *snd_wq; /* send work queue */ struct ud_send_wqe_st *last_posted_snd_wqe; /* pointers to uar context entries */ void *send_uar_context; __u16 post_send_counter; void *rcv_uar_context; __u16 post_rcv_counter; __u32 snd_db_record_index; __u32 rcv_db_record_index; }; struct device_ib_data_st { __u32 mkey; __u32 pd; __u8 port; __u32 qkey; struct eq_st eq; struct udav_st udav; struct udqp_st mads_qp; struct udqp_st ipoib_qp; void *clr_int_addr; __u32 clr_int_data; __u32 uar_idx; void *uar_context_base; void *error_buf_addr; __u32 error_buf_size; }; struct query_fw_st { __u16 fw_rev_major; __u16 fw_rev_minor; __u16 fw_rev_subminor; __u32 error_buf_start_h; __u32 error_buf_start_l; __u32 error_buf_size; __u32 fw_pages; struct addr_64_st eq_ci_table; struct addr_64_st clear_int_addr; }; struct query_adapter_st { __u8 intapin; }; struct vpm_entry_st { __u32 va_h; __u32 va_l; __u32 pa_h; __u32 pa_l; __u8 log2_size; }; #define MAX_VPM_PER_CALL 1 struct map_icm_st { __u32 num_vpm; struct vpm_entry_st vpm_arr[MAX_VPM_PER_CALL]; }; struct init_hca_st { __u32 qpc_base_addr_h; __u32 qpc_base_addr_l; __u8 log_num_of_qp; __u32 eec_base_addr_h; __u32 eec_base_addr_l; __u8 log_num_of_ee; __u32 srqc_base_addr_h; __u32 srqc_base_addr_l; __u8 log_num_of_srq; __u32 cqc_base_addr_h; __u32 cqc_base_addr_l; __u8 log_num_of_cq; __u32 eqpc_base_addr_h; __u32 eqpc_base_addr_l; __u32 eeec_base_addr_h; __u32 eeec_base_addr_l; __u32 eqc_base_addr_h; __u32 eqc_base_addr_l; __u8 log_num_of_eq; __u32 rdb_base_addr_h; __u32 rdb_base_addr_l; __u32 mc_base_addr_h; __u32 mc_base_addr_l; __u16 log_mc_table_entry_sz; __u32 mc_table_hash_sz; __u8 log_mc_table_sz; __u32 mpt_base_addr_h; __u32 mpt_base_addr_l; __u8 log_mpt_sz; __u32 mtt_base_addr_h; __u32 mtt_base_addr_l; __u8 log_max_uars; }; struct dev_lim_st { __u8 log2_rsvd_qps; __u16 qpc_entry_sz; __u8 log2_rsvd_srqs; __u16 srq_entry_sz; __u8 log2_rsvd_ees; __u16 eec_entry_sz; __u8 log2_rsvd_cqs; __u16 cqc_entry_sz; __u8 log2_rsvd_mtts; __u16 mtt_entry_sz; __u8 log2_rsvd_mrws; __u16 mpt_entry_sz; __u8 log2_rsvd_rdbs; __u16 eqc_entry_sz; __u32 max_icm_size_l; __u32 max_icm_size_h; __u8 uar_sz; __u8 num_rsvd_uars; }; static int create_udqp(struct udqp_st *qp); static int destroy_udqp(struct udqp_st *qp); static void *get_send_wqe_buf(void *wqe, __u8 index); static void *get_rcv_wqe_buf(void *wqe, __u8 index); static struct recv_wqe_st *alloc_rcv_wqe(struct udqp_st *qp); static int free_wqe(void *wqe); static int poll_cq(void *cqh, union cqe_st *cqe_p, __u8 * num_cqes); static int poll_eq(struct ib_eqe_st *ib_eqe_p, __u8 * num_eqes); static int post_rcv_buf(struct udqp_st *qp, struct recv_wqe_st *rcv_wqe); static __u32 dev_get_qpn(void *qph); #endif /* __mt25218_h__ */