[DAPL2] Implement a malloc() threshold for the completion reaping byte vector allocat...
[mirror/winof/.git] / ulp / dapl2 / test / dapltest / test / dapl_transaction_util.c
1 /*
2  * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
3  *
4  * This Software is licensed under one of the following licenses:
5  *
6  * 1) under the terms of the "Common Public License 1.0" a copy of which is
7  *    in the file LICENSE.txt in the root directory. The license is also
8  *    available from the Open Source Initiative, see
9  *    http://www.opensource.org/licenses/cpl.php.
10  *
11  * 2) under the terms of the "The BSD License" a copy of which is in the file
12  *    LICENSE2.txt in the root directory. The license is also available from
13  *    the Open Source Initiative, see
14  *    http://www.opensource.org/licenses/bsd-license.php.
15  *
16  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a 
17  *    copy of which is in the file LICENSE3.txt in the root directory. The 
18  *    license is also available from the Open Source Initiative, see
19  *    http://www.opensource.org/licenses/gpl-license.php.
20  *
21  * Licensee has the right to choose one of the above licenses.
22  *
23  * Redistributions of source code must retain the above copyright
24  * notice and one of the license notices.
25  *
26  * Redistributions in binary form must reproduce both the above copyright
27  * notice, one of the license notices in the documentation
28  * and/or other materials provided with the distribution.
29  */
30
31 #include "dapl_proto.h"
32
33 #define DT_LOCAL_COMPLETION_VECTOR_SIZE 32
34
35 /* -----------------------------------------------------------
36  * Post a recv buffer on each of this thread's EPs.
37  */
38 bool
39 DT_handle_post_recv_buf(DT_Tdep_Print_Head * phead,
40                         Ep_Context_t * ep_context,
41                         unsigned int num_eps, int op_indx)
42 {
43         unsigned int i, j;
44
45         for (i = 0; i < num_eps; i++) {
46                 Transaction_Test_Op_t *op = &ep_context[i].op[op_indx];
47                 DAT_LMR_TRIPLET *iov = DT_Bpool_GetIOV(op->bp, 0);
48                 DAT_DTO_COOKIE cookie;
49                 DAT_RETURN ret;
50
51                 /* Prep the inputs */
52                 for (j = 0; j < op->num_segs; j++) {
53                         iov[j].virtual_address = (DAT_VADDR) (uintptr_t)
54                             DT_Bpool_GetBuffer(op->bp, j);
55                         iov[j].segment_length = op->seg_size;
56                         iov[j].lmr_context = DT_Bpool_GetLMR(op->bp, j);
57                 }
58                 cookie.as_64 = ((((DAT_UINT64) i) << 32)
59                                 | (((uintptr_t) DT_Bpool_GetBuffer(op->bp, 0)) &
60                                    0xffffffffUL));
61
62                 /* Post the recv */
63                 ret = dat_ep_post_recv(ep_context[i].ep_handle,
64                                        op->num_segs,
65                                        iov,
66                                        cookie, DAT_COMPLETION_DEFAULT_FLAG);
67
68                 if (ret != DAT_SUCCESS) {
69                         DT_Tdep_PT_Printf(phead,
70                                           "Test Error: dat_ep_post_recv failed: %s\n",
71                                           DT_RetToString(ret));
72                         DT_Test_Error();
73                         return false;
74                 }
75         }
76
77         return true;
78 }
79
80 /* -----------------------------------------------------------
81  * Post a send buffer on each of this thread's EPs.
82  */
83 bool
84 DT_handle_send_op(DT_Tdep_Print_Head * phead,
85                   Ep_Context_t * ep_context,
86                   unsigned int num_eps, int op_indx, bool poll)
87 {
88         unsigned int i, j;
89         unsigned char *completion_reaped;
90         unsigned char lcomp[DT_LOCAL_COMPLETION_VECTOR_SIZE];
91         bool rc = false;
92
93         if (num_eps <= DT_LOCAL_COMPLETION_VECTOR_SIZE) {
94                 completion_reaped = lcomp;
95                 bzero((void *)completion_reaped,
96                         sizeof(unsigned char) * num_eps);
97         }
98         else {
99                 completion_reaped = DT_Mdep_Malloc(num_eps * sizeof(unsigned char));
100                 if (!completion_reaped) {
101                         return false;
102                 }
103         }
104
105         for (i = 0; i < num_eps; i++) {
106                 Transaction_Test_Op_t *op = &ep_context[i].op[op_indx];
107                 DAT_LMR_TRIPLET *iov = DT_Bpool_GetIOV(op->bp, 0);
108                 DAT_DTO_COOKIE cookie;
109                 DAT_RETURN ret;
110
111                 /* Prep the inputs */
112                 for (j = 0; j < op->num_segs; j++) {
113                         iov[j].virtual_address = (DAT_VADDR) (uintptr_t)
114                             DT_Bpool_GetBuffer(op->bp, j);
115                         iov[j].segment_length = op->seg_size;
116                         iov[j].lmr_context = DT_Bpool_GetLMR(op->bp, j);
117                 }
118                 cookie.as_64 = ((((DAT_UINT64) i) << 32)
119                                 | (((uintptr_t) DT_Bpool_GetBuffer(op->bp, 0)) &
120                                    0xffffffffUL));
121
122                 /* Post the send */
123                 ret = dat_ep_post_send(ep_context[i].ep_handle,
124                                        op->num_segs,
125                                        iov,
126                                        cookie, DAT_COMPLETION_DEFAULT_FLAG);
127
128                 if (ret != DAT_SUCCESS) {
129                         DT_Tdep_PT_Printf(phead,
130                                           "Test Error: dat_ep_post_send failed: %s\n",
131                                           DT_RetToString(ret));
132                         DT_Test_Error();
133                         goto xit;
134                 }
135         }
136
137         for (i = 0; i < num_eps; i++) {
138                 Transaction_Test_Op_t *op = &ep_context[i].op[op_indx];
139
140                 if (op->reap_send_on_recv && !op->server_initiated) {
141                         /* we will reap the send on the recv (Client SR) */
142                         rc = true;
143                         goto xit;
144                 }
145         }
146
147         /* reap the send completion */
148         for (i = 0; i < num_eps; i++) {
149                 Transaction_Test_Op_t *op;
150                 DAT_DTO_COMPLETION_EVENT_DATA dto_stat;
151                 DAT_DTO_COOKIE dto_cookie;
152                 unsigned int epnum;
153
154                 if (!DT_dto_event_reap
155                     (phead, ep_context[i].reqt_evd_hdl, poll, &dto_stat)) {
156                         goto xit;
157                 }
158
159                 epnum = dto_stat.user_cookie.as_64 >> 32;
160                 if (epnum > num_eps) {
161                         DT_Tdep_PT_Printf(phead,
162                                           "Test Error: Send: Invalid endpoint completion reaped.\n"
163                                           "\tEndpoint: 0x%p, Cookie: 0x" F64x
164                                           ", Length: " F64u "\n",
165                                           dto_stat.ep_handle,
166                                           dto_stat.user_cookie.as_64,
167                                           dto_stat.transfered_length);
168                         DT_Test_Error();
169                         goto xit;
170                 }
171
172                 op = &ep_context[epnum].op[op_indx];
173
174                 dto_cookie.as_64 = ((((DAT_UINT64) epnum) << 32)
175                                     |
176                                     (((uintptr_t) DT_Bpool_GetBuffer(op->bp, 0))
177                                      & 0xffffffffUL));
178
179                 if (!DT_dto_check(phead,
180                                   &dto_stat,
181                                   ep_context[epnum].ep_handle,
182                                   op->num_segs * op->seg_size,
183                                   dto_cookie, "Send")) {
184                         goto xit;
185                 }
186
187                 if (completion_reaped[epnum]) {
188                         DT_Tdep_PT_Printf(phead,
189                                           "Test Error: Send: Secondary completion seen for endpoint 0x%p (%d)\n",
190                                           ep_context[epnum].ep_handle, epnum);
191                         DT_Test_Error();
192                         goto xit;
193                 }
194                 completion_reaped[epnum] = 1;
195         }
196
197         for (i = 0; i < num_eps; i++) {
198                 if (completion_reaped[i] == 0) {
199                         DT_Tdep_PT_Printf(phead,
200                                           "Test Error: Send: No completion seen for endpoint 0x%p (#%d)\n",
201                                           ep_context[i].ep_handle, i);
202                         DT_Test_Error();
203                         goto xit;
204                 }
205         }
206
207         rc = true;
208
209 xit:
210         if (completion_reaped != lcomp)
211                 DT_Mdep_Free(completion_reaped);
212         return rc;
213 }
214
215 /* -----------------------------------------------------------
216  * Reap a recv op on each of this thread's EPs,
217  * then if requested reap the corresponding send ops,
218  * and re-post all of the recv buffers.
219  */
220 bool
221 DT_handle_recv_op(DT_Tdep_Print_Head * phead,
222                   Ep_Context_t * ep_context,
223                   unsigned int num_eps,
224                   int op_indx, bool poll, bool repost_recv)
225 {
226         unsigned int i;
227         unsigned char *recv_completion_reaped;
228         unsigned char *send_completion_reaped;
229         unsigned char rcomp[DT_LOCAL_COMPLETION_VECTOR_SIZE];
230         unsigned char lcomp[DT_LOCAL_COMPLETION_VECTOR_SIZE];
231         bool rc = false;
232
233         if (num_eps <= DT_LOCAL_COMPLETION_VECTOR_SIZE ) {
234                 recv_completion_reaped = rcomp;
235                 send_completion_reaped = lcomp;
236                 bzero((void *)recv_completion_reaped,
237                         sizeof(unsigned char) * num_eps);
238                 bzero((void *)send_completion_reaped,
239                         sizeof(unsigned char) * num_eps);
240         }
241         else {
242                 recv_completion_reaped = DT_Mdep_Malloc(num_eps);
243                 if (recv_completion_reaped == NULL) {
244                         return false;
245                 }
246
247                 send_completion_reaped = DT_Mdep_Malloc(num_eps);
248                 if (send_completion_reaped == NULL) {
249                         DT_Mdep_Free(recv_completion_reaped);
250                         return false;
251                 }
252         }
253
254         /* Foreach EP, reap */
255         for (i = 0; i < num_eps; i++) {
256                 Transaction_Test_Op_t *op;
257                 DAT_DTO_COMPLETION_EVENT_DATA dto_stat;
258                 DAT_DTO_COOKIE dto_cookie;
259                 unsigned int epnum;
260
261                 /* First reap the recv DTO event */
262                 if (!DT_dto_event_reap
263                     (phead, ep_context[i].recv_evd_hdl, poll, &dto_stat)) {
264                         goto xit;
265                 }
266
267                 epnum = dto_stat.user_cookie.as_64 >> 32;
268                 if (epnum > num_eps) {
269                         DT_Tdep_PT_Printf(phead,
270                                           "Test Error: Receive: Invalid endpoint completion reaped.\n"
271                                           "\tEndpoint: 0x%p, Cookie: 0x" F64x
272                                           ", Length: " F64u "\n",
273                                           dto_stat.ep_handle,
274                                           dto_stat.user_cookie.as_64,
275                                           dto_stat.transfered_length);
276                         DT_Test_Error();
277                         goto xit;
278                 }
279
280                 op = &ep_context[epnum].op[op_indx];
281                 dto_cookie.as_64 = ((((DAT_UINT64) epnum) << 32)
282                                     |
283                                     (((uintptr_t) DT_Bpool_GetBuffer(op->bp, 0))
284                                      & 0xffffffffUL));
285
286                 if (!DT_dto_check(phead,
287                                   &dto_stat,
288                                   ep_context[epnum].ep_handle,
289                                   op->num_segs * op->seg_size,
290                                   dto_cookie, "Recv")) {
291                         DT_Tdep_PT_Printf(phead,
292                                           "Test Error: recv DTO problem\n");
293                         DT_Test_Error();
294                         goto xit;
295                 }
296
297                 if (recv_completion_reaped[epnum]) {
298                         DT_Tdep_PT_Printf(phead,
299                                           "Test Error: Receive: Secondary completion seen for endpoint 0x%p (%d)\n",
300                                           ep_context[epnum].ep_handle, epnum);
301                         DT_Test_Error();
302                         goto xit;
303                 }
304                 recv_completion_reaped[epnum] = 1;
305
306                 /*
307                  * Check the current op to see whether we are supposed
308                  * to reap the previous send op now.
309                  */
310                 if (op->reap_send_on_recv && op->server_initiated) {
311                         if (op_indx <= 0)
312                                 /* shouldn't happen, but let's be certain */
313                         {
314                                 DT_Tdep_PT_Printf(phead,
315                                                   "Internal Error: reap_send_on_recv"
316                                                   " but current op == #%d\n",
317                                                   op_indx);
318                                 goto xit;
319                         }
320
321                         if (!DT_dto_event_reap
322                             (phead, ep_context[i].reqt_evd_hdl, poll,
323                              &dto_stat)) {
324                                 goto xit;
325                         }
326
327                         epnum = dto_stat.user_cookie.as_64 >> 32;
328                         if (epnum > num_eps) {
329                                 DT_Tdep_PT_Printf(phead,
330                                                   "Test Error: Send (ror): Invalid endpoint completion reaped.\n"
331                                                   "\tEndpoint: 0x%p, Cookie: 0x"
332                                                   F64x ", Length: " F64u "\n",
333                                                   dto_stat.ep_handle,
334                                                   dto_stat.user_cookie.as_64,
335                                                   dto_stat.transfered_length);
336                                 DT_Test_Error();
337                                 goto xit;
338                         }
339
340                         /*
341                          * We're reaping the last transaction, a
342                          * send completion that we skipped when it was sent.
343                          */
344                         op = &ep_context[epnum].op[op_indx - 1];
345
346                         dto_cookie.as_64 = ((((DAT_UINT64) epnum) << 32)
347                                             |
348                                             (((uintptr_t)
349                                               DT_Bpool_GetBuffer(op->bp, 0))
350                                              & 0xffffffffUL));
351
352                         /*
353                          * If we have multiple EPs we can't guarantee the order of
354                          * completions, so disable ep_handle check
355                          */
356                         if (!DT_dto_check(phead,
357                                           &dto_stat,
358                                           num_eps ==
359                                           1 ? ep_context[i].ep_handle : NULL,
360                                           op->num_segs * op->seg_size,
361                                           dto_cookie, "Send-reaped-on-recv")) {
362                                 DT_Tdep_PT_Printf(phead,
363                                                   "Test Error: send DTO problem\n");
364                                 DT_Test_Error();
365                                 goto xit;
366                         }
367
368                         if (send_completion_reaped[epnum]) {
369                                 DT_Tdep_PT_Printf(phead,
370                                                   "Test Error: Send (ror): Secondary completion seen for endpoint 0x%p (%d)\n",
371                                                   ep_context[epnum].ep_handle,
372                                                   epnum);
373                                 DT_Test_Error();
374                                 goto xit;
375                         }
376                         send_completion_reaped[epnum] = 1;
377                 }
378         }
379
380         for (i = 0; i < num_eps; i++) {
381                 if (recv_completion_reaped[i] == 0) {
382                         DT_Tdep_PT_Printf(phead,
383                                           "Test Error: Receive: No completion seen for endpoint 0x%p (#%d)\n",
384                                           ep_context[i].ep_handle, i);
385                         DT_Test_Error();
386                         goto xit;
387                 }
388         }
389
390         if (ep_context[0].op[op_indx].reap_send_on_recv
391             && ep_context[0].op[op_indx].server_initiated) {
392                 for (i = 0; i < num_eps; i++) {
393                         if (send_completion_reaped[i] == 0) {
394                                 DT_Tdep_PT_Printf(phead,
395                                                   "Test Error: Send (ror): No completion seen for endpoint 0x%p (#%d)\n",
396                                                   ep_context[i].ep_handle, i);
397                                 DT_Test_Error();
398                                 goto xit;
399                         }
400                 }
401         }
402
403         if (repost_recv) {
404                 /* repost the receive buffer */
405                 if (!DT_handle_post_recv_buf
406                     (phead, ep_context, num_eps, op_indx)) {
407                         DT_Tdep_PT_Printf(phead,
408                                           "Test Error: recv re-post problem\n");
409                         DT_Test_Error();
410                         goto xit;
411                 }
412         }
413         rc = true;
414 xit:
415         if (send_completion_reaped != lcomp) {
416                 DT_Mdep_Free(recv_completion_reaped);
417                 DT_Mdep_Free(send_completion_reaped);
418         }
419         return rc;
420 }
421
422 /* -----------------------------------------------------------
423  * Initiate an RDMA op (synchronous) on each of this thread's EPs.
424  */
425 bool
426 DT_handle_rdma_op(DT_Tdep_Print_Head * phead,
427                   Ep_Context_t * ep_context,
428                   unsigned int num_eps,
429                   DT_Transfer_Type opcode, int op_indx, bool poll)
430 {
431         unsigned int i, j;
432         DAT_RETURN ret;
433         unsigned char *completion_reaped;
434         unsigned char lcomp[DT_LOCAL_COMPLETION_VECTOR_SIZE];
435         bool rc = false;
436
437         if (num_eps <= DT_LOCAL_COMPLETION_VECTOR_SIZE) {
438                 completion_reaped = lcomp;
439                 bzero((void *)completion_reaped, sizeof(unsigned char) * num_eps);
440         }
441         else {
442                 completion_reaped = DT_Mdep_Malloc(num_eps * sizeof(unsigned char));
443                 if (!completion_reaped) {
444                         return false;
445                 }
446         }
447
448         /* Initiate the operation */
449         for (i = 0; i < num_eps; i++) {
450                 Transaction_Test_Op_t *op = &ep_context[i].op[op_indx];
451                 DAT_LMR_TRIPLET *iov = DT_Bpool_GetIOV(op->bp, 0);
452                 DAT_DTO_COOKIE cookie;
453                 DAT_RMR_TRIPLET rmr_triplet;
454
455                 /* Prep the inputs */
456                 for (j = 0; j < op->num_segs; j++) {
457                         iov[j].virtual_address = (DAT_VADDR) (uintptr_t)
458                             DT_Bpool_GetBuffer(op->bp, j);
459                         iov[j].segment_length = op->seg_size;
460                         iov[j].lmr_context = DT_Bpool_GetLMR(op->bp, j);
461                 }
462                 cookie.as_64 = ((((DAT_UINT64) i) << 32)
463                                 | (((uintptr_t) DT_Bpool_GetBuffer(op->bp, 0)) &
464                                    0xffffffffUL));
465
466                 rmr_triplet.virtual_address =
467                     (DAT_VADDR) (uintptr_t) op->Rdma_Address;
468                 rmr_triplet.segment_length = op->seg_size * op->num_segs;
469                 rmr_triplet.rmr_context = op->Rdma_Context;
470
471                 DT_Tdep_PT_Debug(3, (phead,
472                                      "Call dat_ep_post_rdma_%s [" F64x ", sz="
473                                      F64x ", ctxt=%x]\n",
474                                      (opcode == RDMA_WRITE ? "write" : "read"),
475                                      rmr_triplet.virtual_address,
476                                      rmr_triplet.segment_length,
477                                      rmr_triplet.rmr_context));
478
479                 /* Post the operation */
480                 if (opcode == RDMA_WRITE) {
481
482                         ret = dat_ep_post_rdma_write(ep_context[i].ep_handle,
483                                                      op->num_segs,
484                                                      iov,
485                                                      cookie,
486                                                      &rmr_triplet,
487                                                      DAT_COMPLETION_DEFAULT_FLAG);
488
489                 } else {        /* opcode == RDMA_READ */
490
491                         ret = dat_ep_post_rdma_read(ep_context[i].ep_handle,
492                                                     op->num_segs,
493                                                     iov,
494                                                     cookie,
495                                                     &rmr_triplet,
496                                                     DAT_COMPLETION_DEFAULT_FLAG);
497
498                 }
499                 if (ret != DAT_SUCCESS) {
500                         DT_Tdep_PT_Printf(phead,
501                                           "Test Error: dat_ep_post_rdma_%s failed: %s\n",
502                                           (opcode ==
503                                            RDMA_WRITE ? "write" : "read"),
504                                           DT_RetToString(ret));
505                         DT_Test_Error();
506                         goto err;
507                 } else {
508                         DT_Tdep_PT_Debug(3, (phead,
509                                              "Done dat_ep_post_rdma_%s %s\n",
510                                              (opcode ==
511                                               RDMA_WRITE ? "write" : "read"),
512                                              " ()  Waiting ..."));
513                 }
514         }
515
516         /* Wait for it to happen */
517         for (i = 0; i < num_eps; i++) {
518                 Transaction_Test_Op_t *op;
519                 DAT_DTO_COMPLETION_EVENT_DATA dto_stat;
520                 DAT_DTO_COOKIE dto_cookie;
521                 unsigned int epnum;
522
523                 if (!DT_dto_event_reap
524                     (phead, ep_context[i].reqt_evd_hdl, poll, &dto_stat)) {
525                         goto err;
526                 }
527
528                 epnum = dto_stat.user_cookie.as_64 >> 32;
529                 if (epnum > num_eps) {
530                         DT_Tdep_PT_Printf(phead,
531                                           "Test Error: %s: Invalid endpoint completion reaped.\n"
532                                           "\tEndpoint: 0x%p, Cookie: 0x" F64x
533                                           ", Length: " F64u "\n",
534                                           opcode ==
535                                           RDMA_WRITE ? "RDMA/WR" : "RDMA/RD",
536                                           dto_stat.ep_handle,
537                                           dto_stat.user_cookie.as_64,
538                                           dto_stat.transfered_length);
539                         DT_Test_Error();
540                         goto err;
541                 }
542                 op = &ep_context[epnum].op[op_indx];
543
544                 dto_cookie.as_64 = ((((DAT_UINT64) epnum) << 32)
545                                     |
546                                     (((uintptr_t) DT_Bpool_GetBuffer(op->bp, 0))
547                                      & 0xffffffffUL));
548
549                 if (!DT_dto_check(phead,
550                                   &dto_stat,
551                                   ep_context[epnum].ep_handle,
552                                   op->num_segs * op->seg_size,
553                                   dto_cookie,
554                                   (opcode ==
555                                    RDMA_WRITE ? "RDMA/WR" : "RDMA/RD"))) {
556                         goto err;
557                 }
558
559                 if (completion_reaped[epnum]) {
560                         DT_Tdep_PT_Printf(phead,
561                                           "Test Error: %s: Secondary completion seen for endpoint 0x%p (%d)\n",
562                                           opcode ==
563                                           RDMA_WRITE ? "RDMA/WR" : "RDMA/RD",
564                                           ep_context[epnum].ep_handle, epnum);
565                         DT_Test_Error();
566                         goto err;
567                 }
568                 completion_reaped[epnum] = 1;
569
570                 DT_Tdep_PT_Debug(3, (phead,
571                                      "dat_ep_post_rdma_%s OK\n",
572                                      (opcode ==
573                                       RDMA_WRITE ? "RDMA/WR" : "RDMA/RD")));
574         }
575
576         for (i = 0; i < num_eps; i++) {
577                 if (completion_reaped[i] == 0) {
578                         DT_Tdep_PT_Printf(phead,
579                                           "Test Error: %s: No completion seen for endpoint 0x%p (#%d)\n",
580                                           opcode ==
581                                           RDMA_WRITE ? "RDMA/WR" : "RDMA/RD",
582                                           ep_context[i].ep_handle, i);
583                         DT_Test_Error();
584                         goto err;
585                 }
586         }
587
588         rc = true;
589
590 err:
591         if (completion_reaped != lcomp)
592                 DT_Mdep_Free(completion_reaped);
593
594         return rc;
595 }
596
597 /* -----------------------------------------------------------
598  * Verify whether we (the client side) can support
599  * the requested 'T' test.
600  */
601 bool DT_check_params(Per_Test_Data_t * pt_ptr, char *module)
602 {
603         Transaction_Cmd_t *cmd = &pt_ptr->Params.u.Transaction_Cmd;
604         unsigned long num_recvs = 0U;
605         unsigned long num_sends = 0U;
606         unsigned long num_rdma_rd = 0U;
607         unsigned long num_rdma_wr = 0U;
608         unsigned long max_size = 0U;
609         unsigned long max_segs = 0U;
610         bool rval = true;
611         unsigned int i;
612         DT_Tdep_Print_Head *phead;
613
614         phead = pt_ptr->Params.phead;
615
616         /* Count up what's requested (including -V appended sync points) */
617         for (i = 0; i < cmd->num_ops; i++) {
618                 unsigned int xfer_size;
619
620                 xfer_size = cmd->op[i].num_segs * cmd->op[i].seg_size;
621                 if (xfer_size > max_size) {
622                         max_size = xfer_size;
623                 }
624                 if (cmd->op[i].num_segs > max_segs) {
625                         max_segs = cmd->op[i].num_segs;
626                 }
627
628                 switch (cmd->op[i].transfer_type) {
629                 case SEND_RECV:
630                         {
631                                 if (cmd->op[i].server_initiated) {
632                                         num_recvs++;
633                                 } else {
634                                         num_sends++;
635                                 }
636                                 break;
637                         }
638
639                 case RDMA_READ:
640                         {
641                                 num_rdma_rd++;
642                                 break;
643                         }
644
645                 case RDMA_WRITE:
646                         {
647                                 num_rdma_wr++;
648                                 break;
649                         }
650                 }
651         }
652
653         /*
654          * Now check the IA and EP attributes, and check for some of the
655          * more obvious resource problems.  This is hardly exhaustive,
656          * and some things will inevitably fall through to run-time.
657          *
658          * We don't compare
659          *      num_rdma_rd > pt_ptr->ia_attr.max_rdma_read_per_ep
660          *      num_rdma_wr > pt_ptr->ia_attr.max_dto_per_ep
661          * because each thread has its own EPs, and transfers are issued
662          * synchronously (across a thread's EPs, and ignoring -f, which allows
663          * a per-EP pipeline depth of at most 2 and applies only to SR ops),
664          * so dapltest actually attempts almost no pipelining on a single EP.
665          * But we do check that pre-posted recv buffers will all fit.
666          */
667         if (num_recvs > pt_ptr->ia_attr.max_dto_per_ep ||
668             num_sends > pt_ptr->ia_attr.max_dto_per_ep) {
669                 DT_Tdep_PT_Printf(phead,
670                                   "%s: S/R: cannot supply %ld SR ops (maximum: %d)\n",
671                                   module,
672                                   num_recvs > num_sends ? num_recvs : num_sends,
673                                   pt_ptr->ia_attr.max_dto_per_ep);
674                 rval = false;
675         }
676         if (max_size > pt_ptr->ia_attr.max_lmr_block_size) {
677                 DT_Tdep_PT_Printf(phead,
678                                   "%s: buffer too large: 0x%lx (maximum: " F64x
679                                   " bytes)\n", module, max_size,
680                                   pt_ptr->ia_attr.max_lmr_block_size);
681                 rval = false;
682         }
683         if (max_segs > pt_ptr->ep_attr.max_recv_iov ||
684             max_segs > pt_ptr->ep_attr.max_request_iov) {
685                 /*
686                  * In an ideal world, we'd just ask for more segments
687                  * when creating the EPs for the test, rather than
688                  * checking against default EP attributes.
689                  */
690                 DT_Tdep_PT_Printf(phead,
691                                   "%s: cannot use %ld segments (maxima: S %d, R %d)\n",
692                                   module,
693                                   max_segs,
694                                   pt_ptr->ep_attr.max_request_iov,
695                                   pt_ptr->ep_attr.max_recv_iov);
696                 rval = false;
697         }
698
699         return (rval);
700 }
701
702 /* Empty function in which to set breakpoints.  */
703 void DT_Test_Error(void)
704 {
705         ;
706 }
707
708 void
709 DT_Transaction_Cmd_PT_Print(DT_Tdep_Print_Head * phead, Transaction_Cmd_t * cmd)
710 {
711         unsigned int i;
712         DT_Tdep_PT_Printf(phead, "-------------------------------------\n");
713         DT_Tdep_PT_Printf(phead, "TransCmd.server_name              : %s\n",
714                           cmd->server_name);
715         DT_Tdep_PT_Printf(phead, "TransCmd.num_iterations           : %d\n",
716                           cmd->num_iterations);
717         DT_Tdep_PT_Printf(phead, "TransCmd.num_threads              : %d\n",
718                           cmd->num_threads);
719         DT_Tdep_PT_Printf(phead, "TransCmd.eps_per_thread           : %d\n",
720                           cmd->eps_per_thread);
721         DT_Tdep_PT_Printf(phead, "TransCmd.validate                 : %d\n",
722                           cmd->validate);
723         DT_Tdep_PT_Printf(phead, "TransCmd.dapl_name                : %s\n",
724                           cmd->dapl_name);
725         DT_Tdep_PT_Printf(phead, "TransCmd.num_ops                  : %d\n",
726                           cmd->num_ops);
727
728         for (i = 0; i < cmd->num_ops; i++) {
729                 DT_Tdep_PT_Printf(phead,
730                                   "TransCmd.op[%d].transfer_type      : %s %s\n",
731                                   i,
732                                   cmd->op[i].transfer_type ==
733                                   0 ? "RDMA_READ" : cmd->op[i].transfer_type ==
734                                   1 ? "RDMA_WRITE" : "SEND_RECV",
735                                   cmd->op[i].
736                                   server_initiated ? " (server)" : " (client)");
737                 DT_Tdep_PT_Printf(phead,
738                                   "TransCmd.op[%d].seg_size           : %d\n",
739                                   i, cmd->op[i].seg_size);
740                 DT_Tdep_PT_Printf(phead,
741                                   "TransCmd.op[%d].num_segs           : %d\n",
742                                   i, cmd->op[i].num_segs);
743                 DT_Tdep_PT_Printf(phead,
744                                   "TransCmd.op[%d].reap_send_on_recv  : %d\n",
745                                   i, cmd->op[i].reap_send_on_recv);
746         }
747 }