14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * hermon_srq.c
28 * Hermon Shared Receive Queue Processing Routines
29 *
30 * Implements all the routines necessary for allocating, freeing, querying,
31 * modifying and posting shared receive queues.
32 */
33
34 #include <sys/types.h>
35 #include <sys/conf.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/modctl.h>
39 #include <sys/bitmap.h>
40
41 #include <sys/ib/adapters/hermon/hermon.h>
42
43 static void hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl,
44 hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl);
45
46 /*
47 * hermon_srq_alloc()
48 * Context: Can be called only from user or kernel context.
49 */
50 int
51 hermon_srq_alloc(hermon_state_t *state, hermon_srq_info_t *srqinfo,
52 uint_t sleepflag)
53 {
157 /*
158 * Allocate the doorbell record. Hermon just needs one for the
159 * SRQ, and use uarpg (above) as the uar index
160 */
161
162 status = hermon_dbr_alloc(state, uarpg, &srq->srq_wq_dbr_acchdl,
163 &srq->srq_wq_vdbr, &srq->srq_wq_pdbr, &srq->srq_rdbr_mapoffset);
164 if (status != DDI_SUCCESS) {
165 status = IBT_INSUFF_RESOURCE;
166 goto srqalloc_fail4;
167 }
168
169 /*
170 * Calculate the appropriate size for the SRQ.
171 * Note: All Hermon SRQs must be a power-of-2 in size. Also
172 * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step
173 * is to round the requested size up to the next highest power-of-2
174 */
175 srq_wr_sz = max(sizes->srq_wr_sz + 1, HERMON_SRQ_MIN_SIZE);
176 log_srq_size = highbit(srq_wr_sz);
177 if ((srq_wr_sz & (srq_wr_sz - 1)) == 0) {
178 log_srq_size = log_srq_size - 1;
179 }
180
181 /*
182 * Next we verify that the rounded-up size is valid (i.e. consistent
183 * with the device limits and/or software-configured limits). If not,
184 * then obviously we have a lot of cleanup to do before returning.
185 */
186 if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) {
187 status = IBT_HCA_WR_EXCEEDED;
188 goto srqalloc_fail4a;
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->hs_ibtfinfo.hca_attr->hca_max_srq_sgl;
197 if (sizes->srq_sgl_sz > max_sgl) {
606 (state->hs_cfg_profile->cp_srq_resize_enabled == 0))
607 return (IBT_NOT_SUPPORTED);
608
609 /*
610 * If size requested is larger than device capability, return
611 * Insufficient Resources
612 */
613 max_srq_size = (1 << state->hs_cfg_profile->cp_log_max_srq_sz);
614 if (size > max_srq_size) {
615 return (IBT_HCA_WR_EXCEEDED);
616 }
617
618 /*
619 * Calculate the appropriate size for the SRQ.
620 * Note: All Hermon SRQs must be a power-of-2 in size. Also
621 * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step
622 * is to round the requested size up to the next highest power-of-2
623 */
624 size = max(size, HERMON_SRQ_MIN_SIZE);
625 log_srq_size = highbit(size);
626 if ((size & (size - 1)) == 0) {
627 log_srq_size = log_srq_size - 1;
628 }
629
630 /*
631 * Next we verify that the rounded-up size is valid (i.e. consistent
632 * with the device limits and/or software-configured limits).
633 */
634 if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) {
635 status = IBT_HCA_WR_EXCEEDED;
636 goto srqmodify_fail;
637 }
638
639 /*
640 * Allocate the memory for newly resized Shared Receive Queue.
641 *
642 * Note: If SRQ is not user-mappable, then it may come from either
643 * kernel system memory or from HCA-attached local DDR memory.
644 *
645 * Note2: We align this queue on a pagesize boundary. This is required
646 * to make sure that all the resulting IB addresses will start at 0,
957
958 /*
959 * hermon_srq_sgl_to_logwqesz()
960 * Context: Can be called from interrupt or base context.
961 */
962 static void
963 hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl,
964 hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl)
965 {
966 uint_t max_size, log2, actual_sgl;
967
968 switch (wq_type) {
969 case HERMON_QP_WQ_TYPE_RECVQ:
970 /*
971 * Use requested maximum SGL to calculate max descriptor size
972 * (while guaranteeing that the descriptor size is a
973 * power-of-2 cachelines).
974 */
975 max_size = (HERMON_QP_WQE_MLX_SRQ_HDRS + (num_sgl << 4));
976 log2 = highbit(max_size);
977 if ((max_size & (max_size - 1)) == 0) {
978 log2 = log2 - 1;
979 }
980
981 /* Make sure descriptor is at least the minimum size */
982 log2 = max(log2, HERMON_QP_WQE_LOG_MINIMUM);
983
984 /* Calculate actual number of SGL (given WQE size) */
985 actual_sgl = ((1 << log2) - HERMON_QP_WQE_MLX_SRQ_HDRS) >> 4;
986 break;
987
988 default:
989 HERMON_WARNING(state, "unexpected work queue type");
990 break;
991 }
992
993 /* Fill in the return values */
994 *logwqesz = log2;
995 *max_sgl = min(state->hs_cfg_profile->cp_srq_max_sgl, actual_sgl);
996 }
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * hermon_srq.c
28 * Hermon Shared Receive Queue Processing Routines
29 *
30 * Implements all the routines necessary for allocating, freeing, querying,
31 * modifying and posting shared receive queues.
32 */
33
34 #include <sys/sysmacros.h>
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/hermon/hermon.h>
43
44 static void hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl,
45 hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl);
46
47 /*
48 * hermon_srq_alloc()
49 * Context: Can be called only from user or kernel context.
50 */
51 int
52 hermon_srq_alloc(hermon_state_t *state, hermon_srq_info_t *srqinfo,
53 uint_t sleepflag)
54 {
158 /*
159 * Allocate the doorbell record. Hermon just needs one for the
160 * SRQ, and use uarpg (above) as the uar index
161 */
162
163 status = hermon_dbr_alloc(state, uarpg, &srq->srq_wq_dbr_acchdl,
164 &srq->srq_wq_vdbr, &srq->srq_wq_pdbr, &srq->srq_rdbr_mapoffset);
165 if (status != DDI_SUCCESS) {
166 status = IBT_INSUFF_RESOURCE;
167 goto srqalloc_fail4;
168 }
169
170 /*
171 * Calculate the appropriate size for the SRQ.
172 * Note: All Hermon SRQs must be a power-of-2 in size. Also
173 * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step
174 * is to round the requested size up to the next highest power-of-2
175 */
176 srq_wr_sz = max(sizes->srq_wr_sz + 1, HERMON_SRQ_MIN_SIZE);
177 log_srq_size = highbit(srq_wr_sz);
178 if (ISP2(srq_wr_sz)) {
179 log_srq_size = log_srq_size - 1;
180 }
181
182 /*
183 * Next we verify that the rounded-up size is valid (i.e. consistent
184 * with the device limits and/or software-configured limits). If not,
185 * then obviously we have a lot of cleanup to do before returning.
186 */
187 if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) {
188 status = IBT_HCA_WR_EXCEEDED;
189 goto srqalloc_fail4a;
190 }
191
192 /*
193 * Next we verify that the requested number of SGL is valid (i.e.
194 * consistent with the device limits and/or software-configured
195 * limits). If not, then obviously the same cleanup needs to be done.
196 */
197 max_sgl = state->hs_ibtfinfo.hca_attr->hca_max_srq_sgl;
198 if (sizes->srq_sgl_sz > max_sgl) {
607 (state->hs_cfg_profile->cp_srq_resize_enabled == 0))
608 return (IBT_NOT_SUPPORTED);
609
610 /*
611 * If size requested is larger than device capability, return
612 * Insufficient Resources
613 */
614 max_srq_size = (1 << state->hs_cfg_profile->cp_log_max_srq_sz);
615 if (size > max_srq_size) {
616 return (IBT_HCA_WR_EXCEEDED);
617 }
618
619 /*
620 * Calculate the appropriate size for the SRQ.
621 * Note: All Hermon SRQs must be a power-of-2 in size. Also
622 * they may not be any smaller than HERMON_SRQ_MIN_SIZE. This step
623 * is to round the requested size up to the next highest power-of-2
624 */
625 size = max(size, HERMON_SRQ_MIN_SIZE);
626 log_srq_size = highbit(size);
627 if (ISP2(size)) {
628 log_srq_size = log_srq_size - 1;
629 }
630
631 /*
632 * Next we verify that the rounded-up size is valid (i.e. consistent
633 * with the device limits and/or software-configured limits).
634 */
635 if (log_srq_size > state->hs_cfg_profile->cp_log_max_srq_sz) {
636 status = IBT_HCA_WR_EXCEEDED;
637 goto srqmodify_fail;
638 }
639
640 /*
641 * Allocate the memory for newly resized Shared Receive Queue.
642 *
643 * Note: If SRQ is not user-mappable, then it may come from either
644 * kernel system memory or from HCA-attached local DDR memory.
645 *
646 * Note2: We align this queue on a pagesize boundary. This is required
647 * to make sure that all the resulting IB addresses will start at 0,
958
959 /*
960 * hermon_srq_sgl_to_logwqesz()
961 * Context: Can be called from interrupt or base context.
962 */
963 static void
964 hermon_srq_sgl_to_logwqesz(hermon_state_t *state, uint_t num_sgl,
965 hermon_qp_wq_type_t wq_type, uint_t *logwqesz, uint_t *max_sgl)
966 {
967 uint_t max_size, log2, actual_sgl;
968
969 switch (wq_type) {
970 case HERMON_QP_WQ_TYPE_RECVQ:
971 /*
972 * Use requested maximum SGL to calculate max descriptor size
973 * (while guaranteeing that the descriptor size is a
974 * power-of-2 cachelines).
975 */
976 max_size = (HERMON_QP_WQE_MLX_SRQ_HDRS + (num_sgl << 4));
977 log2 = highbit(max_size);
978 if (ISP2(max_size)) {
979 log2 = log2 - 1;
980 }
981
982 /* Make sure descriptor is at least the minimum size */
983 log2 = max(log2, HERMON_QP_WQE_LOG_MINIMUM);
984
985 /* Calculate actual number of SGL (given WQE size) */
986 actual_sgl = ((1 << log2) - HERMON_QP_WQE_MLX_SRQ_HDRS) >> 4;
987 break;
988
989 default:
990 HERMON_WARNING(state, "unexpected work queue type");
991 break;
992 }
993
994 /* Fill in the return values */
995 *logwqesz = log2;
996 *max_sgl = min(state->hs_cfg_profile->cp_srq_max_sgl, actual_sgl);
997 }
|