Print this page
5255 uts shouldn't open-code ISP2


  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);