1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * OpenIB.org BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32  * SOFTWARE.
33  *
34  */
35 
36 /*
37  * Abstract:
38  *    Implementation of osm_mad_pool_t.
39  * This object represents a pool of management datagram (MAD) objects.
40  * This object is part of the opensm family of objects.
41  */
42 
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif				/* HAVE_CONFIG_H */
46 
47 #include <stdlib.h>
48 #include <string.h>
49 #include <opensm/osm_file_ids.h>
50 #define FILE_ID OSM_FILE_MAD_POOL_C
51 #include <opensm/osm_mad_pool.h>
52 #include <opensm/osm_madw.h>
53 #include <vendor/osm_vendor_api.h>
54 
55 void osm_mad_pool_construct(IN osm_mad_pool_t * p_pool)
56 {
57 	CL_ASSERT(p_pool);
58 
59 	memset(p_pool, 0, sizeof(*p_pool));
60 }
61 
62 void osm_mad_pool_destroy(IN osm_mad_pool_t * p_pool)
63 {
64 	CL_ASSERT(p_pool);
65 }
66 
67 ib_api_status_t osm_mad_pool_init(IN osm_mad_pool_t * p_pool)
68 {
69 	p_pool->mads_out = 0;
70 
71 	return IB_SUCCESS;
72 }
73 
74 osm_madw_t *osm_mad_pool_get(IN osm_mad_pool_t * p_pool,
75 			     IN osm_bind_handle_t h_bind,
76 			     IN uint32_t total_size,
77 			     IN const osm_mad_addr_t * p_mad_addr)
78 {
79 	osm_madw_t *p_madw;
80 	ib_mad_t *p_mad;
81 
82 	CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);
83 	CL_ASSERT(total_size);
84 
85 	/*
86 	   First, acquire a mad wrapper from the mad wrapper pool.
87 	 */
88 	p_madw = malloc(sizeof(*p_madw));
89 	if (p_madw == NULL)
90 		goto Exit;
91 
92 	osm_madw_init(p_madw, h_bind, total_size, p_mad_addr);
93 
94 	/*
95 	   Next, acquire a wire mad of the specified size.
96 	 */
97 	p_mad = osm_vendor_get(h_bind, total_size, &p_madw->vend_wrap);
98 	if (p_mad == NULL) {
99 		/* Don't leak wrappers! */
100 		free(p_madw);
101 		p_madw = NULL;
102 		goto Exit;
103 	}
104 
105 	cl_atomic_inc(&p_pool->mads_out);
106 	/*
107 	   Finally, attach the wire MAD to this wrapper.
108 	 */
109 	osm_madw_set_mad(p_madw, p_mad);
110 
111 Exit:
112 	return p_madw;
113 }
114 
115 osm_madw_t *osm_mad_pool_get_wrapper(IN osm_mad_pool_t * p_pool,
116 				     IN osm_bind_handle_t h_bind,
117 				     IN uint32_t total_size,
118 				     IN const ib_mad_t * p_mad,
119 				     IN const osm_mad_addr_t * p_mad_addr)
120 {
121 	osm_madw_t *p_madw;
122 
123 	CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);
124 	CL_ASSERT(total_size);
125 	CL_ASSERT(p_mad);
126 
127 	/*
128 	   First, acquire a mad wrapper from the mad wrapper pool.
129 	 */
130 	p_madw = malloc(sizeof(*p_madw));
131 	if (p_madw == NULL)
132 		goto Exit;
133 
134 	/*
135 	   Finally, initialize the wrapper object.
136 	 */
137 	cl_atomic_inc(&p_pool->mads_out);
138 	osm_madw_init(p_madw, h_bind, total_size, p_mad_addr);
139 	osm_madw_set_mad(p_madw, p_mad);
140 
141 Exit:
142 	return p_madw;
143 }
144 
145 osm_madw_t *osm_mad_pool_get_wrapper_raw(IN osm_mad_pool_t * p_pool)
146 {
147 	osm_madw_t *p_madw;
148 
149 	p_madw = malloc(sizeof(*p_madw));
150 	if (!p_madw)
151 		return NULL;
152 
153 	osm_madw_init(p_madw, 0, 0, 0);
154 	osm_madw_set_mad(p_madw, 0);
155 	cl_atomic_inc(&p_pool->mads_out);
156 
157 	return p_madw;
158 }
159 
160 void osm_mad_pool_put(IN osm_mad_pool_t * p_pool, IN osm_madw_t * p_madw)
161 {
162 	CL_ASSERT(p_madw);
163 
164 	/*
165 	   First, return the wire mad to the pool
166 	 */
167 	if (p_madw->p_mad)
168 		osm_vendor_put(p_madw->h_bind, &p_madw->vend_wrap);
169 
170 	/*
171 	   Return the mad wrapper to the wrapper pool
172 	 */
173 	free(p_madw);
174 	cl_atomic_dec(&p_pool->mads_out);
175 }
176