856 if (ddi_copyin((void *)arg, &info, sizeof (hermon_ports_ioctl_t),
857 mode) != 0) {
858 return (EFAULT);
859 }
860
861 /*
862 * Check ioctl revision
863 */
864 if (info.ap_revision != HERMON_VTS_IOCTL_REVISION) {
865 return (EINVAL);
866 }
867
868 /* Allocate space for temporary GID table/PKey table */
869 tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
870 sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t),
871 KM_SLEEP);
872 tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
873 pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t),
874 KM_SLEEP);
875
876 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*sgid_tbl, *pkey_tbl))
877
878 /*
879 * Setup the number of ports, then loop through all ports and
880 * query properties of each.
881 */
882 info.ap_num_ports = (uint8_t)state->hs_cfg_profile->cp_num_ports;
883 for (i = 0; i < info.ap_num_ports; i++) {
884 /*
885 * Get portstate information from the device. If
886 * hermon_port_query() fails, leave zeroes in user
887 * struct port entry and continue.
888 */
889 bzero(&pi, sizeof (ibt_hca_portinfo_t));
890 pi.p_sgid_tbl = sgid_tbl;
891 pi.p_pkey_tbl = pkey_tbl;
892 (void) hermon_port_query(state, i + 1, &pi);
893
894 portstat.asp_port_num = pi.p_port_num;
895 portstat.asp_state = pi.p_linkstate;
896 portstat.asp_guid = pi.p_sgid_tbl[0].gid_guid;
897
934 return (EFAULT);
935 }
936
937 return (0);
938 }
939
940 /*
941 * hermon_ioctl_loopback()
942 */
943 static int
944 hermon_ioctl_loopback(hermon_state_t *state, intptr_t arg, int mode)
945 {
946 hermon_loopback_ioctl_t lb;
947 hermon_loopback_state_t lstate;
948 ibt_hca_portinfo_t pi;
949 uint_t tbl_size, loopmax, max_usec;
950 ib_gid_t *sgid_tbl;
951 ib_pkey_t *pkey_tbl;
952 int j, iter, ret;
953
954 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(lstate))
955
956 /*
957 * Access to Hemron VTS ioctls is not allowed in "maintenance mode".
958 */
959 if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
960 return (EFAULT);
961 }
962
963 /* copyin the user struct to kernel */
964 #ifdef _MULTI_DATAMODEL
965 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
966 hermon_loopback_ioctl32_t lb32;
967
968 if (ddi_copyin((void *)arg, &lb32,
969 sizeof (hermon_loopback_ioctl32_t), mode) != 0) {
970 return (EFAULT);
971 }
972 lb.alb_revision = lb32.alb_revision;
973 lb.alb_send_buf = (caddr_t)(uintptr_t)lb32.alb_send_buf;
974 lb.alb_fail_buf = (caddr_t)(uintptr_t)lb32.alb_fail_buf;
975 lb.alb_buf_sz = lb32.alb_buf_sz;
2132 }
2133
2134 /*
2135 * hermon_flash_bank()
2136 */
2137 static int
2138 hermon_flash_bank(hermon_state_t *state, uint32_t addr)
2139 {
2140 ddi_acc_handle_t hdl;
2141 uint32_t bank;
2142
2143 /* initialize the FMA retry loop */
2144 hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
2145
2146 /* Set handle */
2147 hdl = hermon_get_pcihdl(state);
2148
2149 /* Determine the bank setting from the address */
2150 bank = addr & HERMON_HW_FLASH_BANK_MASK;
2151
2152 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(state->hs_fw_flashbank))
2153
2154 /*
2155 * If the bank is different from the currently set bank, we need to
2156 * change it. Also, if an 'addr' of 0 is given, this allows the
2157 * capability to force the flash bank to 0. This is useful at init
2158 * time to initially set the bank value
2159 */
2160 if (state->hs_fw_flashbank != bank || addr == 0) {
2161 switch (state->hs_fw_cmdset) {
2162 case HERMON_FLASH_SPI_CMDSET:
2163 /* CMJ: not needed for hermon */
2164 break;
2165
2166 case HERMON_FLASH_INTEL_CMDSET:
2167 case HERMON_FLASH_AMD_CMDSET:
2168 /* the FMA retry loop starts. */
2169 hermon_pio_start(state, hdl, pio_error, fm_loop_cnt,
2170 fm_status, fm_test);
2171
2172 hermon_flash_write_cfg(state, hdl,
2173 HERMON_HW_FLASH_GPIO_DATACLEAR, 0x70);
2755 }
2756
2757 static void
2758 hermon_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i)
2759 {
2760 *dword = (uint32_t)
2761 ((uint32_t)ch[i] << 24 |
2762 (uint32_t)ch[i+1] << 16 |
2763 (uint32_t)ch[i+2] << 8 |
2764 (uint32_t)ch[i+3]);
2765 }
2766
2767 /*
2768 * hermon_loopback_free_qps
2769 */
2770 static void
2771 hermon_loopback_free_qps(hermon_loopback_state_t *lstate)
2772 {
2773 int i;
2774
2775 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2776
2777 if (lstate->hls_tx.hlc_qp_hdl != NULL) {
2778 (void) hermon_qp_free(lstate->hls_state,
2779 &lstate->hls_tx.hlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
2780 HERMON_NOSLEEP);
2781 }
2782 if (lstate->hls_rx.hlc_qp_hdl != NULL) {
2783 (void) hermon_qp_free(lstate->hls_state,
2784 &lstate->hls_rx.hlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
2785 HERMON_NOSLEEP);
2786 }
2787 lstate->hls_tx.hlc_qp_hdl = NULL;
2788 lstate->hls_rx.hlc_qp_hdl = NULL;
2789 for (i = 0; i < 2; i++) {
2790 if (lstate->hls_tx.hlc_cqhdl[i] != NULL) {
2791 (void) hermon_cq_free(lstate->hls_state,
2792 &lstate->hls_tx.hlc_cqhdl[i], HERMON_NOSLEEP);
2793 }
2794 if (lstate->hls_rx.hlc_cqhdl[i] != NULL) {
2795 (void) hermon_cq_free(lstate->hls_state,
2796 &lstate->hls_rx.hlc_cqhdl[i], HERMON_NOSLEEP);
2818 HERMON_NOSLEEP);
2819 }
2820 if (lstate->hls_pd_hdl != NULL) {
2821 (void) hermon_pd_free(lstate->hls_state, &lstate->hls_pd_hdl);
2822 }
2823 if (lstate->hls_tx.hlc_buf != NULL) {
2824 kmem_free(lstate->hls_tx.hlc_buf, lstate->hls_tx.hlc_buf_sz);
2825 }
2826 if (lstate->hls_rx.hlc_buf != NULL) {
2827 kmem_free(lstate->hls_rx.hlc_buf, lstate->hls_rx.hlc_buf_sz);
2828 }
2829 bzero(lstate, sizeof (hermon_loopback_state_t));
2830 }
2831
2832 /*
2833 * hermon_loopback_init
2834 */
2835 static int
2836 hermon_loopback_init(hermon_state_t *state, hermon_loopback_state_t *lstate)
2837 {
2838 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2839
2840 lstate->hls_hca_hdl = (ibc_hca_hdl_t)state;
2841 lstate->hls_status = hermon_pd_alloc(lstate->hls_state,
2842 &lstate->hls_pd_hdl, HERMON_NOSLEEP);
2843 if (lstate->hls_status != IBT_SUCCESS) {
2844 lstate->hls_err = HERMON_LOOPBACK_PROT_DOMAIN_ALLOC_FAIL;
2845 return (EFAULT);
2846 }
2847
2848 return (0);
2849 }
2850
2851 /*
2852 * hermon_loopback_init_qp_info
2853 */
2854 static void
2855 hermon_loopback_init_qp_info(hermon_loopback_state_t *lstate,
2856 hermon_loopback_comm_t *comm)
2857 {
2858 bzero(&comm->hlc_cq_attr, sizeof (ibt_cq_attr_t));
2859 bzero(&comm->hlc_qp_attr, sizeof (ibt_qp_alloc_attr_t));
2882 comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_send_grh = 0;
2883 comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid =
2884 lstate->hls_lid;
2885 comm->hlc_qp_info.qp_transport.rc.rc_retry_cnt = lstate->hls_retry;
2886 comm->hlc_qp_info.qp_transport.rc.rc_sq_psn = 0;
2887 comm->hlc_qp_info.qp_transport.rc.rc_rq_psn = 0;
2888 comm->hlc_qp_info.qp_transport.rc.rc_rdma_ra_in = 4;
2889 comm->hlc_qp_info.qp_transport.rc.rc_rdma_ra_out = 4;
2890 comm->hlc_qp_info.qp_transport.rc.rc_dst_qpn = 0;
2891 comm->hlc_qp_info.qp_transport.rc.rc_min_rnr_nak = IBT_RNR_NAK_655ms;
2892 comm->hlc_qp_info.qp_transport.rc.rc_path_mtu = IB_MTU_1K;
2893 }
2894
2895 /*
2896 * hermon_loopback_alloc_mem
2897 */
2898 static int
2899 hermon_loopback_alloc_mem(hermon_loopback_state_t *lstate,
2900 hermon_loopback_comm_t *comm, int sz)
2901 {
2902 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2903
2904 /* Allocate buffer of specified size */
2905 comm->hlc_buf_sz = sz;
2906 comm->hlc_buf = kmem_zalloc(sz, KM_NOSLEEP);
2907 if (comm->hlc_buf == NULL) {
2908 return (EFAULT);
2909 }
2910
2911 /* Register the buffer as a memory region */
2912 comm->hlc_memattr.mr_vaddr = (uint64_t)(uintptr_t)comm->hlc_buf;
2913 comm->hlc_memattr.mr_len = (ib_msglen_t)sz;
2914 comm->hlc_memattr.mr_as = NULL;
2915 comm->hlc_memattr.mr_flags = IBT_MR_NOSLEEP |
2916 IBT_MR_ENABLE_REMOTE_WRITE | IBT_MR_ENABLE_LOCAL_WRITE;
2917
2918 comm->hlc_status = hermon_mr_register(lstate->hls_state,
2919 lstate->hls_pd_hdl, &comm->hlc_memattr, &comm->hlc_mrhdl,
2920 NULL, HERMON_MPT_DMPT);
2921
2922 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm->hlc_mrhdl))
2923
2924 comm->hlc_mrdesc.md_vaddr = comm->hlc_mrhdl->mr_bindinfo.bi_addr;
2925 comm->hlc_mrdesc.md_lkey = comm->hlc_mrhdl->mr_lkey;
2926 comm->hlc_mrdesc.md_rkey = comm->hlc_mrhdl->mr_rkey;
2927 if (comm->hlc_status != IBT_SUCCESS) {
2928 return (EFAULT);
2929 }
2930 return (0);
2931 }
2932
2933 /*
2934 * hermon_loopback_alloc_qps
2935 */
2936 static int
2937 hermon_loopback_alloc_qps(hermon_loopback_state_t *lstate,
2938 hermon_loopback_comm_t *comm)
2939 {
2940 uint32_t i, real_size;
2941 hermon_qp_info_t qpinfo;
2942
2943 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2944 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2945
2946 /* Allocate send and recv CQs */
2947 for (i = 0; i < 2; i++) {
2948 bzero(&comm->hlc_cq_attr, sizeof (ibt_cq_attr_t));
2949 comm->hlc_cq_attr.cq_size = 128;
2950 comm->hlc_status = hermon_cq_alloc(lstate->hls_state,
2951 (ibt_cq_hdl_t)NULL, &comm->hlc_cq_attr, &real_size,
2952 &comm->hlc_cqhdl[i], HERMON_NOSLEEP);
2953 if (comm->hlc_status != IBT_SUCCESS) {
2954 lstate->hls_err += i;
2955 return (EFAULT);
2956 }
2957 }
2958
2959 /* Allocate the QP */
2960 hermon_loopback_init_qp_info(lstate, comm);
2961 comm->hlc_qp_attr.qp_pd_hdl = (ibt_pd_hdl_t)lstate->hls_pd_hdl;
2962 comm->hlc_qp_attr.qp_scq_hdl = (ibt_cq_hdl_t)comm->hlc_cqhdl[0];
2963 comm->hlc_qp_attr.qp_rcq_hdl = (ibt_cq_hdl_t)comm->hlc_cqhdl[1];
2964 comm->hlc_qp_attr.qp_ibc_scq_hdl = (ibt_opaque1_t)comm->hlc_cqhdl[0];
2965 comm->hlc_qp_attr.qp_ibc_rcq_hdl = (ibt_opaque1_t)comm->hlc_cqhdl[1];
2971 comm->hlc_status = hermon_qp_alloc(lstate->hls_state, &qpinfo,
2972 HERMON_NOSLEEP);
2973 if (comm->hlc_status == DDI_SUCCESS) {
2974 comm->hlc_qp_hdl = qpinfo.qpi_qphdl;
2975 }
2976
2977 if (comm->hlc_status != IBT_SUCCESS) {
2978 lstate->hls_err += 2;
2979 return (EFAULT);
2980 }
2981 return (0);
2982 }
2983
2984 /*
2985 * hermon_loopback_modify_qp
2986 */
2987 static int
2988 hermon_loopback_modify_qp(hermon_loopback_state_t *lstate,
2989 hermon_loopback_comm_t *comm, uint_t qp_num)
2990 {
2991 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
2992 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*lstate))
2993
2994 /* Modify QP to INIT */
2995 hermon_loopback_init_qp_info(lstate, comm);
2996 comm->hlc_qp_info.qp_state = IBT_STATE_INIT;
2997 comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
2998 IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
2999 if (comm->hlc_status != IBT_SUCCESS) {
3000 return (EFAULT);
3001 }
3002
3003 /*
3004 * Modify QP to RTR (set destination LID and QP number to local
3005 * LID and QP number)
3006 */
3007 comm->hlc_qp_info.qp_state = IBT_STATE_RTR;
3008 comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid
3009 = lstate->hls_lid;
3010 comm->hlc_qp_info.qp_transport.rc.rc_dst_qpn = qp_num;
3011 comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
3012 IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
3013 if (comm->hlc_status != IBT_SUCCESS) {
3055 return (EFAULT);
3056 }
3057 } else
3058 #endif /* _MULTI_DATAMODEL */
3059 if (ddi_copyout(lb, (void *)arg, sizeof (hermon_loopback_ioctl_t),
3060 mode) != 0) {
3061 return (EFAULT);
3062 }
3063 return (0);
3064 }
3065
3066 /*
3067 * hermon_loopback_post_send
3068 */
3069 static int
3070 hermon_loopback_post_send(hermon_loopback_state_t *lstate,
3071 hermon_loopback_comm_t *tx, hermon_loopback_comm_t *rx)
3072 {
3073 int ret;
3074
3075 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*tx))
3076
3077 bzero(&tx->hlc_sgl, sizeof (ibt_wr_ds_t));
3078 bzero(&tx->hlc_wr, sizeof (ibt_send_wr_t));
3079
3080 /* Initialize local address for TX buffer */
3081 tx->hlc_sgl.ds_va = tx->hlc_mrdesc.md_vaddr;
3082 tx->hlc_sgl.ds_key = tx->hlc_mrdesc.md_lkey;
3083 tx->hlc_sgl.ds_len = tx->hlc_buf_sz;
3084
3085 /* Initialize the remaining details of the work request */
3086 tx->hlc_wr.wr_id = tx->hlc_wrid++;
3087 tx->hlc_wr.wr_flags = IBT_WR_SEND_SIGNAL;
3088 tx->hlc_wr.wr_nds = 1;
3089 tx->hlc_wr.wr_sgl = &tx->hlc_sgl;
3090 tx->hlc_wr.wr_opcode = IBT_WRC_RDMAW;
3091 tx->hlc_wr.wr_trans = IBT_RC_SRV;
3092
3093 /* Initialize the remote address for RX buffer */
3094 tx->hlc_wr.wr.rc.rcwr.rdma.rdma_raddr = rx->hlc_mrdesc.md_vaddr;
3095 tx->hlc_wr.wr.rc.rcwr.rdma.rdma_rkey = rx->hlc_mrdesc.md_rkey;
3096 tx->hlc_complete = 0;
3097 ret = hermon_post_send(lstate->hls_state, tx->hlc_qp_hdl, &tx->hlc_wr,
3098 1, NULL);
3099 if (ret != IBT_SUCCESS) {
3100 return (EFAULT);
3101 }
3102 return (0);
3103 }
3104
3105 /*
3106 * hermon_loopback_poll_cq
3107 */
3108 static int
3109 hermon_loopback_poll_cq(hermon_loopback_state_t *lstate,
3110 hermon_loopback_comm_t *comm)
3111 {
3112 _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*comm))
3113
3114 comm->hlc_wc.wc_status = 0;
3115 comm->hlc_num_polled = 0;
3116 comm->hlc_status = hermon_cq_poll(lstate->hls_state,
3117 comm->hlc_cqhdl[0], &comm->hlc_wc, 1, &comm->hlc_num_polled);
3118 if ((comm->hlc_status == IBT_SUCCESS) &&
3119 (comm->hlc_wc.wc_status != IBT_WC_SUCCESS)) {
3120 comm->hlc_status = ibc_get_ci_failure(0);
3121 }
3122 return (comm->hlc_status);
3123 }
|
856 if (ddi_copyin((void *)arg, &info, sizeof (hermon_ports_ioctl_t),
857 mode) != 0) {
858 return (EFAULT);
859 }
860
861 /*
862 * Check ioctl revision
863 */
864 if (info.ap_revision != HERMON_VTS_IOCTL_REVISION) {
865 return (EINVAL);
866 }
867
868 /* Allocate space for temporary GID table/PKey table */
869 tbl_size = (1 << state->hs_cfg_profile->cp_log_max_gidtbl);
870 sgid_tbl = (ib_gid_t *)kmem_zalloc(tbl_size * sizeof (ib_gid_t),
871 KM_SLEEP);
872 tbl_size = (1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
873 pkey_tbl = (ib_pkey_t *)kmem_zalloc(tbl_size * sizeof (ib_pkey_t),
874 KM_SLEEP);
875
876 /*
877 * Setup the number of ports, then loop through all ports and
878 * query properties of each.
879 */
880 info.ap_num_ports = (uint8_t)state->hs_cfg_profile->cp_num_ports;
881 for (i = 0; i < info.ap_num_ports; i++) {
882 /*
883 * Get portstate information from the device. If
884 * hermon_port_query() fails, leave zeroes in user
885 * struct port entry and continue.
886 */
887 bzero(&pi, sizeof (ibt_hca_portinfo_t));
888 pi.p_sgid_tbl = sgid_tbl;
889 pi.p_pkey_tbl = pkey_tbl;
890 (void) hermon_port_query(state, i + 1, &pi);
891
892 portstat.asp_port_num = pi.p_port_num;
893 portstat.asp_state = pi.p_linkstate;
894 portstat.asp_guid = pi.p_sgid_tbl[0].gid_guid;
895
932 return (EFAULT);
933 }
934
935 return (0);
936 }
937
938 /*
939 * hermon_ioctl_loopback()
940 */
941 static int
942 hermon_ioctl_loopback(hermon_state_t *state, intptr_t arg, int mode)
943 {
944 hermon_loopback_ioctl_t lb;
945 hermon_loopback_state_t lstate;
946 ibt_hca_portinfo_t pi;
947 uint_t tbl_size, loopmax, max_usec;
948 ib_gid_t *sgid_tbl;
949 ib_pkey_t *pkey_tbl;
950 int j, iter, ret;
951
952 /*
953 * Access to Hemron VTS ioctls is not allowed in "maintenance mode".
954 */
955 if (state->hs_operational_mode == HERMON_MAINTENANCE_MODE) {
956 return (EFAULT);
957 }
958
959 /* copyin the user struct to kernel */
960 #ifdef _MULTI_DATAMODEL
961 if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
962 hermon_loopback_ioctl32_t lb32;
963
964 if (ddi_copyin((void *)arg, &lb32,
965 sizeof (hermon_loopback_ioctl32_t), mode) != 0) {
966 return (EFAULT);
967 }
968 lb.alb_revision = lb32.alb_revision;
969 lb.alb_send_buf = (caddr_t)(uintptr_t)lb32.alb_send_buf;
970 lb.alb_fail_buf = (caddr_t)(uintptr_t)lb32.alb_fail_buf;
971 lb.alb_buf_sz = lb32.alb_buf_sz;
2128 }
2129
2130 /*
2131 * hermon_flash_bank()
2132 */
2133 static int
2134 hermon_flash_bank(hermon_state_t *state, uint32_t addr)
2135 {
2136 ddi_acc_handle_t hdl;
2137 uint32_t bank;
2138
2139 /* initialize the FMA retry loop */
2140 hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
2141
2142 /* Set handle */
2143 hdl = hermon_get_pcihdl(state);
2144
2145 /* Determine the bank setting from the address */
2146 bank = addr & HERMON_HW_FLASH_BANK_MASK;
2147
2148 /*
2149 * If the bank is different from the currently set bank, we need to
2150 * change it. Also, if an 'addr' of 0 is given, this allows the
2151 * capability to force the flash bank to 0. This is useful at init
2152 * time to initially set the bank value
2153 */
2154 if (state->hs_fw_flashbank != bank || addr == 0) {
2155 switch (state->hs_fw_cmdset) {
2156 case HERMON_FLASH_SPI_CMDSET:
2157 /* CMJ: not needed for hermon */
2158 break;
2159
2160 case HERMON_FLASH_INTEL_CMDSET:
2161 case HERMON_FLASH_AMD_CMDSET:
2162 /* the FMA retry loop starts. */
2163 hermon_pio_start(state, hdl, pio_error, fm_loop_cnt,
2164 fm_status, fm_test);
2165
2166 hermon_flash_write_cfg(state, hdl,
2167 HERMON_HW_FLASH_GPIO_DATACLEAR, 0x70);
2749 }
2750
2751 static void
2752 hermon_flash_cfi_dword(uint32_t *dword, uint8_t *ch, int i)
2753 {
2754 *dword = (uint32_t)
2755 ((uint32_t)ch[i] << 24 |
2756 (uint32_t)ch[i+1] << 16 |
2757 (uint32_t)ch[i+2] << 8 |
2758 (uint32_t)ch[i+3]);
2759 }
2760
2761 /*
2762 * hermon_loopback_free_qps
2763 */
2764 static void
2765 hermon_loopback_free_qps(hermon_loopback_state_t *lstate)
2766 {
2767 int i;
2768
2769 if (lstate->hls_tx.hlc_qp_hdl != NULL) {
2770 (void) hermon_qp_free(lstate->hls_state,
2771 &lstate->hls_tx.hlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
2772 HERMON_NOSLEEP);
2773 }
2774 if (lstate->hls_rx.hlc_qp_hdl != NULL) {
2775 (void) hermon_qp_free(lstate->hls_state,
2776 &lstate->hls_rx.hlc_qp_hdl, IBC_FREE_QP_AND_QPN, NULL,
2777 HERMON_NOSLEEP);
2778 }
2779 lstate->hls_tx.hlc_qp_hdl = NULL;
2780 lstate->hls_rx.hlc_qp_hdl = NULL;
2781 for (i = 0; i < 2; i++) {
2782 if (lstate->hls_tx.hlc_cqhdl[i] != NULL) {
2783 (void) hermon_cq_free(lstate->hls_state,
2784 &lstate->hls_tx.hlc_cqhdl[i], HERMON_NOSLEEP);
2785 }
2786 if (lstate->hls_rx.hlc_cqhdl[i] != NULL) {
2787 (void) hermon_cq_free(lstate->hls_state,
2788 &lstate->hls_rx.hlc_cqhdl[i], HERMON_NOSLEEP);
2810 HERMON_NOSLEEP);
2811 }
2812 if (lstate->hls_pd_hdl != NULL) {
2813 (void) hermon_pd_free(lstate->hls_state, &lstate->hls_pd_hdl);
2814 }
2815 if (lstate->hls_tx.hlc_buf != NULL) {
2816 kmem_free(lstate->hls_tx.hlc_buf, lstate->hls_tx.hlc_buf_sz);
2817 }
2818 if (lstate->hls_rx.hlc_buf != NULL) {
2819 kmem_free(lstate->hls_rx.hlc_buf, lstate->hls_rx.hlc_buf_sz);
2820 }
2821 bzero(lstate, sizeof (hermon_loopback_state_t));
2822 }
2823
2824 /*
2825 * hermon_loopback_init
2826 */
2827 static int
2828 hermon_loopback_init(hermon_state_t *state, hermon_loopback_state_t *lstate)
2829 {
2830 lstate->hls_hca_hdl = (ibc_hca_hdl_t)state;
2831 lstate->hls_status = hermon_pd_alloc(lstate->hls_state,
2832 &lstate->hls_pd_hdl, HERMON_NOSLEEP);
2833 if (lstate->hls_status != IBT_SUCCESS) {
2834 lstate->hls_err = HERMON_LOOPBACK_PROT_DOMAIN_ALLOC_FAIL;
2835 return (EFAULT);
2836 }
2837
2838 return (0);
2839 }
2840
2841 /*
2842 * hermon_loopback_init_qp_info
2843 */
2844 static void
2845 hermon_loopback_init_qp_info(hermon_loopback_state_t *lstate,
2846 hermon_loopback_comm_t *comm)
2847 {
2848 bzero(&comm->hlc_cq_attr, sizeof (ibt_cq_attr_t));
2849 bzero(&comm->hlc_qp_attr, sizeof (ibt_qp_alloc_attr_t));
2872 comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_send_grh = 0;
2873 comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid =
2874 lstate->hls_lid;
2875 comm->hlc_qp_info.qp_transport.rc.rc_retry_cnt = lstate->hls_retry;
2876 comm->hlc_qp_info.qp_transport.rc.rc_sq_psn = 0;
2877 comm->hlc_qp_info.qp_transport.rc.rc_rq_psn = 0;
2878 comm->hlc_qp_info.qp_transport.rc.rc_rdma_ra_in = 4;
2879 comm->hlc_qp_info.qp_transport.rc.rc_rdma_ra_out = 4;
2880 comm->hlc_qp_info.qp_transport.rc.rc_dst_qpn = 0;
2881 comm->hlc_qp_info.qp_transport.rc.rc_min_rnr_nak = IBT_RNR_NAK_655ms;
2882 comm->hlc_qp_info.qp_transport.rc.rc_path_mtu = IB_MTU_1K;
2883 }
2884
2885 /*
2886 * hermon_loopback_alloc_mem
2887 */
2888 static int
2889 hermon_loopback_alloc_mem(hermon_loopback_state_t *lstate,
2890 hermon_loopback_comm_t *comm, int sz)
2891 {
2892 /* Allocate buffer of specified size */
2893 comm->hlc_buf_sz = sz;
2894 comm->hlc_buf = kmem_zalloc(sz, KM_NOSLEEP);
2895 if (comm->hlc_buf == NULL) {
2896 return (EFAULT);
2897 }
2898
2899 /* Register the buffer as a memory region */
2900 comm->hlc_memattr.mr_vaddr = (uint64_t)(uintptr_t)comm->hlc_buf;
2901 comm->hlc_memattr.mr_len = (ib_msglen_t)sz;
2902 comm->hlc_memattr.mr_as = NULL;
2903 comm->hlc_memattr.mr_flags = IBT_MR_NOSLEEP |
2904 IBT_MR_ENABLE_REMOTE_WRITE | IBT_MR_ENABLE_LOCAL_WRITE;
2905
2906 comm->hlc_status = hermon_mr_register(lstate->hls_state,
2907 lstate->hls_pd_hdl, &comm->hlc_memattr, &comm->hlc_mrhdl,
2908 NULL, HERMON_MPT_DMPT);
2909
2910 comm->hlc_mrdesc.md_vaddr = comm->hlc_mrhdl->mr_bindinfo.bi_addr;
2911 comm->hlc_mrdesc.md_lkey = comm->hlc_mrhdl->mr_lkey;
2912 comm->hlc_mrdesc.md_rkey = comm->hlc_mrhdl->mr_rkey;
2913 if (comm->hlc_status != IBT_SUCCESS) {
2914 return (EFAULT);
2915 }
2916 return (0);
2917 }
2918
2919 /*
2920 * hermon_loopback_alloc_qps
2921 */
2922 static int
2923 hermon_loopback_alloc_qps(hermon_loopback_state_t *lstate,
2924 hermon_loopback_comm_t *comm)
2925 {
2926 uint32_t i, real_size;
2927 hermon_qp_info_t qpinfo;
2928
2929 /* Allocate send and recv CQs */
2930 for (i = 0; i < 2; i++) {
2931 bzero(&comm->hlc_cq_attr, sizeof (ibt_cq_attr_t));
2932 comm->hlc_cq_attr.cq_size = 128;
2933 comm->hlc_status = hermon_cq_alloc(lstate->hls_state,
2934 (ibt_cq_hdl_t)NULL, &comm->hlc_cq_attr, &real_size,
2935 &comm->hlc_cqhdl[i], HERMON_NOSLEEP);
2936 if (comm->hlc_status != IBT_SUCCESS) {
2937 lstate->hls_err += i;
2938 return (EFAULT);
2939 }
2940 }
2941
2942 /* Allocate the QP */
2943 hermon_loopback_init_qp_info(lstate, comm);
2944 comm->hlc_qp_attr.qp_pd_hdl = (ibt_pd_hdl_t)lstate->hls_pd_hdl;
2945 comm->hlc_qp_attr.qp_scq_hdl = (ibt_cq_hdl_t)comm->hlc_cqhdl[0];
2946 comm->hlc_qp_attr.qp_rcq_hdl = (ibt_cq_hdl_t)comm->hlc_cqhdl[1];
2947 comm->hlc_qp_attr.qp_ibc_scq_hdl = (ibt_opaque1_t)comm->hlc_cqhdl[0];
2948 comm->hlc_qp_attr.qp_ibc_rcq_hdl = (ibt_opaque1_t)comm->hlc_cqhdl[1];
2954 comm->hlc_status = hermon_qp_alloc(lstate->hls_state, &qpinfo,
2955 HERMON_NOSLEEP);
2956 if (comm->hlc_status == DDI_SUCCESS) {
2957 comm->hlc_qp_hdl = qpinfo.qpi_qphdl;
2958 }
2959
2960 if (comm->hlc_status != IBT_SUCCESS) {
2961 lstate->hls_err += 2;
2962 return (EFAULT);
2963 }
2964 return (0);
2965 }
2966
2967 /*
2968 * hermon_loopback_modify_qp
2969 */
2970 static int
2971 hermon_loopback_modify_qp(hermon_loopback_state_t *lstate,
2972 hermon_loopback_comm_t *comm, uint_t qp_num)
2973 {
2974 /* Modify QP to INIT */
2975 hermon_loopback_init_qp_info(lstate, comm);
2976 comm->hlc_qp_info.qp_state = IBT_STATE_INIT;
2977 comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
2978 IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
2979 if (comm->hlc_status != IBT_SUCCESS) {
2980 return (EFAULT);
2981 }
2982
2983 /*
2984 * Modify QP to RTR (set destination LID and QP number to local
2985 * LID and QP number)
2986 */
2987 comm->hlc_qp_info.qp_state = IBT_STATE_RTR;
2988 comm->hlc_qp_info.qp_transport.rc.rc_path.cep_adds_vect.av_dlid
2989 = lstate->hls_lid;
2990 comm->hlc_qp_info.qp_transport.rc.rc_dst_qpn = qp_num;
2991 comm->hlc_status = hermon_qp_modify(lstate->hls_state, comm->hlc_qp_hdl,
2992 IBT_CEP_SET_STATE, &comm->hlc_qp_info, &comm->hlc_queue_sizes);
2993 if (comm->hlc_status != IBT_SUCCESS) {
3035 return (EFAULT);
3036 }
3037 } else
3038 #endif /* _MULTI_DATAMODEL */
3039 if (ddi_copyout(lb, (void *)arg, sizeof (hermon_loopback_ioctl_t),
3040 mode) != 0) {
3041 return (EFAULT);
3042 }
3043 return (0);
3044 }
3045
3046 /*
3047 * hermon_loopback_post_send
3048 */
3049 static int
3050 hermon_loopback_post_send(hermon_loopback_state_t *lstate,
3051 hermon_loopback_comm_t *tx, hermon_loopback_comm_t *rx)
3052 {
3053 int ret;
3054
3055 bzero(&tx->hlc_sgl, sizeof (ibt_wr_ds_t));
3056 bzero(&tx->hlc_wr, sizeof (ibt_send_wr_t));
3057
3058 /* Initialize local address for TX buffer */
3059 tx->hlc_sgl.ds_va = tx->hlc_mrdesc.md_vaddr;
3060 tx->hlc_sgl.ds_key = tx->hlc_mrdesc.md_lkey;
3061 tx->hlc_sgl.ds_len = tx->hlc_buf_sz;
3062
3063 /* Initialize the remaining details of the work request */
3064 tx->hlc_wr.wr_id = tx->hlc_wrid++;
3065 tx->hlc_wr.wr_flags = IBT_WR_SEND_SIGNAL;
3066 tx->hlc_wr.wr_nds = 1;
3067 tx->hlc_wr.wr_sgl = &tx->hlc_sgl;
3068 tx->hlc_wr.wr_opcode = IBT_WRC_RDMAW;
3069 tx->hlc_wr.wr_trans = IBT_RC_SRV;
3070
3071 /* Initialize the remote address for RX buffer */
3072 tx->hlc_wr.wr.rc.rcwr.rdma.rdma_raddr = rx->hlc_mrdesc.md_vaddr;
3073 tx->hlc_wr.wr.rc.rcwr.rdma.rdma_rkey = rx->hlc_mrdesc.md_rkey;
3074 tx->hlc_complete = 0;
3075 ret = hermon_post_send(lstate->hls_state, tx->hlc_qp_hdl, &tx->hlc_wr,
3076 1, NULL);
3077 if (ret != IBT_SUCCESS) {
3078 return (EFAULT);
3079 }
3080 return (0);
3081 }
3082
3083 /*
3084 * hermon_loopback_poll_cq
3085 */
3086 static int
3087 hermon_loopback_poll_cq(hermon_loopback_state_t *lstate,
3088 hermon_loopback_comm_t *comm)
3089 {
3090 comm->hlc_wc.wc_status = 0;
3091 comm->hlc_num_polled = 0;
3092 comm->hlc_status = hermon_cq_poll(lstate->hls_state,
3093 comm->hlc_cqhdl[0], &comm->hlc_wc, 1, &comm->hlc_num_polled);
3094 if ((comm->hlc_status == IBT_SUCCESS) &&
3095 (comm->hlc_wc.wc_status != IBT_WC_SUCCESS)) {
3096 comm->hlc_status = ibc_get_ci_failure(0);
3097 }
3098 return (comm->hlc_status);
3099 }
|