1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
2 /*
3 * Copyright (c) 2004-2011 The Trustees of Indiana University and Indiana
4 * University Research and Technology
5 * Corporation. All rights reserved.
6 * Copyright (c) 2004-2009 The University of Tennessee and The University
7 * of Tennessee Research Foundation. All rights
8 * reserved.
9 * Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
10 * University of Stuttgart. All rights reserved.
11 * Copyright (c) 2004-2005 The Regents of the University of California.
12 * All rights reserved.
13 * Copyright (c) 2006-2007 Voltaire. All rights reserved.
14 * Copyright (c) 2009 Cisco Systems, Inc. All rights reserved.
15 * Copyright (c) 2010-2015 Los Alamos National Security, LLC. All rights
16 * reserved.
17 * Copyright (c) 2015 Mellanox Technologies. All rights reserved.
18 *
19 * $COPYRIGHT$
20 *
21 * Additional copyrights may follow
22 *
23 * $HEADER$
24 */
25
26 #include "opal_config.h"
27
28 #include "btl_vader.h"
29 #include "btl_vader_frag.h"
30 #include "btl_vader_fifo.h"
31
32 #include "btl_vader_fbox.h"
33
34 /**
35 * Initiate an inline send to the peer.
36 *
37 * @param btl (IN) BTL module
38 * @param peer (IN) BTL peer addressing
39 */
40 int mca_btl_vader_sendi (struct mca_btl_base_module_t *btl,
41 struct mca_btl_base_endpoint_t *endpoint,
42 struct opal_convertor_t *convertor,
43 void *header, size_t header_size,
44 size_t payload_size, uint8_t order,
45 uint32_t flags, mca_btl_base_tag_t tag,
46 mca_btl_base_descriptor_t **descriptor)
47 {
48 mca_btl_vader_frag_t *frag;
49 void *data_ptr = NULL;
50 size_t length;
51
52 /* don't attempt sendi if there are pending fragments on the endpoint */
53 if (OPAL_UNLIKELY(opal_list_get_size (&endpoint->pending_frags))) {
54 if (descriptor) {
55 *descriptor = NULL;
56 }
57
58 return OPAL_ERR_OUT_OF_RESOURCE;
59 }
60
61 if (payload_size) {
62 opal_convertor_get_current_pointer (convertor, &data_ptr);
63 }
64
65 if (!(payload_size && opal_convertor_need_buffers (convertor)) &&
66 mca_btl_vader_fbox_sendi (endpoint, tag, header, header_size, data_ptr, payload_size)) {
67 return OPAL_SUCCESS;
68 }
69
70 length = header_size + payload_size;
71
72 /* allocate a fragment, giving up if we can't get one */
73 frag = (mca_btl_vader_frag_t *) mca_btl_vader_alloc (btl, endpoint, order, length,
74 flags | MCA_BTL_DES_FLAGS_BTL_OWNERSHIP);
75 if (OPAL_UNLIKELY(NULL == frag)) {
76 if (descriptor) {
77 *descriptor = NULL;
78 }
79
80 return OPAL_ERR_OUT_OF_RESOURCE;
81 }
82
83 /* fill in fragment fields */
84 frag->hdr->len = length;
85 frag->hdr->tag = tag;
86
87 /* write the match header (with MPI comm/tag/etc. info) */
88 memcpy (frag->segments[0].seg_addr.pval, header, header_size);
89
90 /* write the message data if there is any */
91 /* we can't use single-copy semantics here since as caller will consider the send
92 complete when we return */
93 if (payload_size) {
94 uint32_t iov_count = 1;
95 struct iovec iov;
96
97 /* pack the data into the supplied buffer */
98 iov.iov_base = (IOVBASE_TYPE *)((uintptr_t)frag->segments[0].seg_addr.pval + header_size);
99 iov.iov_len = length = payload_size;
100
101 (void) opal_convertor_pack (convertor, &iov, &iov_count, &length);
102
103 assert (length == payload_size);
104 }
105
106 /* write the fragment pointer to peer's the FIFO. the progress function will return the fragment */
107 if (!vader_fifo_write_ep (frag->hdr, endpoint)) {
108 if (descriptor) {
109 *descriptor = &frag->base;
110 } else {
111 mca_btl_vader_free (btl, &frag->base);
112 }
113 return OPAL_ERR_OUT_OF_RESOURCE;
114 }
115
116 return OPAL_SUCCESS;
117 }