15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * tavor_srq.c
29 * Tavor Shared Receive Queue Processing Routines
30 *
31 * Implements all the routines necessary for allocating, freeing, querying,
32 * modifying and posting shared receive queues.
33 */
34
35 #include <sys/types.h>
36 #include <sys/conf.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/modctl.h>
40 #include <sys/bitmap.h>
41
42 #include <sys/ib/adapters/tavor/tavor.h>
43
44 static void tavor_srq_sgl_to_logwqesz(tavor_state_t *state, uint_t num_sgl,
45 tavor_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl);
46
47 /*
48 * tavor_srq_alloc()
49 * Context: Can be called only from user or kernel context.
50 */
51 int
52 tavor_srq_alloc(tavor_state_t *state, tavor_srq_info_t *srqinfo,
53 uint_t sleepflag, tavor_srq_options_t *op)
54 {
155 */
156 if (srq_is_umap) {
157 umapdb = tavor_umap_db_alloc(state->ts_instance,
158 srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC,
159 (uint64_t)(uintptr_t)rsrc);
160 if (umapdb == NULL) {
161 /* Set "status" and "errormsg" and goto failure */
162 TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed umap add");
163 goto srqalloc_fail3;
164 }
165 }
166
167 /*
168 * Calculate the appropriate size for the SRQ.
169 * Note: All Tavor SRQs must be a power-of-2 in size. Also
170 * they may not be any smaller than TAVOR_SRQ_MIN_SIZE. This step
171 * is to round the requested size up to the next highest power-of-2
172 */
173 sizes->srq_wr_sz = max(sizes->srq_wr_sz, TAVOR_SRQ_MIN_SIZE);
174 log_srq_size = highbit(sizes->srq_wr_sz);
175 if ((sizes->srq_wr_sz & (sizes->srq_wr_sz - 1)) == 0) {
176 log_srq_size = log_srq_size - 1;
177 }
178
179 /*
180 * Next we verify that the rounded-up size is valid (i.e. consistent
181 * with the device limits and/or software-configured limits). If not,
182 * then obviously we have a lot of cleanup to do before returning.
183 */
184 if (log_srq_size > state->ts_cfg_profile->cp_log_max_srq_sz) {
185 /* Set "status" and "errormsg" and goto failure */
186 TAVOR_TNF_FAIL(IBT_HCA_WR_EXCEEDED, "max SRQ size");
187 goto srqalloc_fail4;
188 }
189
190 /*
191 * Next we verify that the requested number of SGL is valid (i.e.
192 * consistent with the device limits and/or software-configured
193 * limits). If not, then obviously the same cleanup needs to be done.
194 */
195 max_sgl = state->ts_cfg_profile->cp_srq_max_sgl;
669 /*
670 * If size requested is larger than device capability, return
671 * Insufficient Resources
672 */
673 max_srq_size = (1 << state->ts_cfg_profile->cp_log_max_srq_sz);
674 if (size > max_srq_size) {
675 TNF_PROBE_0(tavor_srq_modify_size_larger_than_maxsize,
676 TAVOR_TNF_ERROR, "");
677 TAVOR_TNF_EXIT(tavor_srq_modify);
678 return (IBT_HCA_WR_EXCEEDED);
679 }
680
681 /*
682 * Calculate the appropriate size for the SRQ.
683 * Note: All Tavor SRQs must be a power-of-2 in size. Also
684 * they may not be any smaller than TAVOR_SRQ_MIN_SIZE. This step
685 * is to round the requested size up to the next highest power-of-2
686 */
687 size = max(size, TAVOR_SRQ_MIN_SIZE);
688 log_srq_size = highbit(size);
689 if ((size & (size - 1)) == 0) {
690 log_srq_size = log_srq_size - 1;
691 }
692
693 /*
694 * Next we verify that the rounded-up size is valid (i.e. consistent
695 * with the device limits and/or software-configured limits).
696 */
697 if (log_srq_size > state->ts_cfg_profile->cp_log_max_srq_sz) {
698 /* Set "status" and "errormsg" and goto failure */
699 TAVOR_TNF_FAIL(IBT_HCA_WR_EXCEEDED, "max SRQ size");
700 goto srqmodify_fail;
701 }
702
703 /*
704 * Allocate the memory for newly resized Shared Receive Queue.
705 *
706 * Note: If SRQ is not user-mappable, then it may come from either
707 * kernel system memory or from HCA-attached local DDR memory.
708 *
709 * Note2: We align this queue on a pagesize boundary. This is required
1082 * tavor_srq_sgl_to_logwqesz()
1083 * Context: Can be called from interrupt or base context.
1084 */
1085 static void
1086 tavor_srq_sgl_to_logwqesz(tavor_state_t *state, uint_t num_sgl,
1087 tavor_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl)
1088 {
1089 uint_t max_size, log2, actual_sgl;
1090
1091 TAVOR_TNF_ENTER(tavor_srq_sgl_to_logwqesz);
1092
1093 switch (wq_type) {
1094 case TAVOR_QP_WQ_TYPE_RECVQ:
1095 /*
1096 * Use requested maximum SGL to calculate max descriptor size
1097 * (while guaranteeing that the descriptor size is a
1098 * power-of-2 cachelines).
1099 */
1100 max_size = (TAVOR_QP_WQE_MLX_RCV_HDRS + (num_sgl << 4));
1101 log2 = highbit(max_size);
1102 if ((max_size & (max_size - 1)) == 0) {
1103 log2 = log2 - 1;
1104 }
1105
1106 /* Make sure descriptor is at least the minimum size */
1107 log2 = max(log2, TAVOR_QP_WQE_LOG_MINIMUM);
1108
1109 /* Calculate actual number of SGL (given WQE size) */
1110 actual_sgl = ((1 << log2) - TAVOR_QP_WQE_MLX_RCV_HDRS) >> 4;
1111 break;
1112
1113 default:
1114 TAVOR_WARNING(state, "unexpected work queue type");
1115 TNF_PROBE_0(tavor_srq_sgl_to_logwqesz_inv_wqtype_fail,
1116 TAVOR_TNF_ERROR, "");
1117 break;
1118 }
1119
1120 /* Fill in the return values */
1121 *logwqesz = log2;
1122 *max_sgl = min(state->ts_cfg_profile->cp_srq_max_sgl, actual_sgl);
|
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * tavor_srq.c
29 * Tavor Shared Receive Queue Processing Routines
30 *
31 * Implements all the routines necessary for allocating, freeing, querying,
32 * modifying and posting shared receive queues.
33 */
34
35 #include <sys/sysmacros.h>
36 #include <sys/types.h>
37 #include <sys/conf.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/modctl.h>
41 #include <sys/bitmap.h>
42
43 #include <sys/ib/adapters/tavor/tavor.h>
44
45 static void tavor_srq_sgl_to_logwqesz(tavor_state_t *state, uint_t num_sgl,
46 tavor_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl);
47
48 /*
49 * tavor_srq_alloc()
50 * Context: Can be called only from user or kernel context.
51 */
52 int
53 tavor_srq_alloc(tavor_state_t *state, tavor_srq_info_t *srqinfo,
54 uint_t sleepflag, tavor_srq_options_t *op)
55 {
156 */
157 if (srq_is_umap) {
158 umapdb = tavor_umap_db_alloc(state->ts_instance,
159 srq->srq_srqnum, MLNX_UMAP_SRQMEM_RSRC,
160 (uint64_t)(uintptr_t)rsrc);
161 if (umapdb == NULL) {
162 /* Set "status" and "errormsg" and goto failure */
163 TAVOR_TNF_FAIL(IBT_INSUFF_RESOURCE, "failed umap add");
164 goto srqalloc_fail3;
165 }
166 }
167
168 /*
169 * Calculate the appropriate size for the SRQ.
170 * Note: All Tavor SRQs must be a power-of-2 in size. Also
171 * they may not be any smaller than TAVOR_SRQ_MIN_SIZE. This step
172 * is to round the requested size up to the next highest power-of-2
173 */
174 sizes->srq_wr_sz = max(sizes->srq_wr_sz, TAVOR_SRQ_MIN_SIZE);
175 log_srq_size = highbit(sizes->srq_wr_sz);
176 if (ISP2(sizes->srq_wr_sz)) {
177 log_srq_size = log_srq_size - 1;
178 }
179
180 /*
181 * Next we verify that the rounded-up size is valid (i.e. consistent
182 * with the device limits and/or software-configured limits). If not,
183 * then obviously we have a lot of cleanup to do before returning.
184 */
185 if (log_srq_size > state->ts_cfg_profile->cp_log_max_srq_sz) {
186 /* Set "status" and "errormsg" and goto failure */
187 TAVOR_TNF_FAIL(IBT_HCA_WR_EXCEEDED, "max SRQ size");
188 goto srqalloc_fail4;
189 }
190
191 /*
192 * Next we verify that the requested number of SGL is valid (i.e.
193 * consistent with the device limits and/or software-configured
194 * limits). If not, then obviously the same cleanup needs to be done.
195 */
196 max_sgl = state->ts_cfg_profile->cp_srq_max_sgl;
670 /*
671 * If size requested is larger than device capability, return
672 * Insufficient Resources
673 */
674 max_srq_size = (1 << state->ts_cfg_profile->cp_log_max_srq_sz);
675 if (size > max_srq_size) {
676 TNF_PROBE_0(tavor_srq_modify_size_larger_than_maxsize,
677 TAVOR_TNF_ERROR, "");
678 TAVOR_TNF_EXIT(tavor_srq_modify);
679 return (IBT_HCA_WR_EXCEEDED);
680 }
681
682 /*
683 * Calculate the appropriate size for the SRQ.
684 * Note: All Tavor SRQs must be a power-of-2 in size. Also
685 * they may not be any smaller than TAVOR_SRQ_MIN_SIZE. This step
686 * is to round the requested size up to the next highest power-of-2
687 */
688 size = max(size, TAVOR_SRQ_MIN_SIZE);
689 log_srq_size = highbit(size);
690 if (ISP2(size)) {
691 log_srq_size = log_srq_size - 1;
692 }
693
694 /*
695 * Next we verify that the rounded-up size is valid (i.e. consistent
696 * with the device limits and/or software-configured limits).
697 */
698 if (log_srq_size > state->ts_cfg_profile->cp_log_max_srq_sz) {
699 /* Set "status" and "errormsg" and goto failure */
700 TAVOR_TNF_FAIL(IBT_HCA_WR_EXCEEDED, "max SRQ size");
701 goto srqmodify_fail;
702 }
703
704 /*
705 * Allocate the memory for newly resized Shared Receive Queue.
706 *
707 * Note: If SRQ is not user-mappable, then it may come from either
708 * kernel system memory or from HCA-attached local DDR memory.
709 *
710 * Note2: We align this queue on a pagesize boundary. This is required
1083 * tavor_srq_sgl_to_logwqesz()
1084 * Context: Can be called from interrupt or base context.
1085 */
1086 static void
1087 tavor_srq_sgl_to_logwqesz(tavor_state_t *state, uint_t num_sgl,
1088 tavor_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl)
1089 {
1090 uint_t max_size, log2, actual_sgl;
1091
1092 TAVOR_TNF_ENTER(tavor_srq_sgl_to_logwqesz);
1093
1094 switch (wq_type) {
1095 case TAVOR_QP_WQ_TYPE_RECVQ:
1096 /*
1097 * Use requested maximum SGL to calculate max descriptor size
1098 * (while guaranteeing that the descriptor size is a
1099 * power-of-2 cachelines).
1100 */
1101 max_size = (TAVOR_QP_WQE_MLX_RCV_HDRS + (num_sgl << 4));
1102 log2 = highbit(max_size);
1103 if (ISP2(max_size)) {
1104 log2 = log2 - 1;
1105 }
1106
1107 /* Make sure descriptor is at least the minimum size */
1108 log2 = max(log2, TAVOR_QP_WQE_LOG_MINIMUM);
1109
1110 /* Calculate actual number of SGL (given WQE size) */
1111 actual_sgl = ((1 << log2) - TAVOR_QP_WQE_MLX_RCV_HDRS) >> 4;
1112 break;
1113
1114 default:
1115 TAVOR_WARNING(state, "unexpected work queue type");
1116 TNF_PROBE_0(tavor_srq_sgl_to_logwqesz_inv_wqtype_fail,
1117 TAVOR_TNF_ERROR, "");
1118 break;
1119 }
1120
1121 /* Fill in the return values */
1122 *logwqesz = log2;
1123 *max_sgl = min(state->ts_cfg_profile->cp_srq_max_sgl, actual_sgl);
|