1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
3*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
4*d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
5*d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6*d6b92ffaSHans Petter Selasky *
7*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
8*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
9*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
10*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
11*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
12*d6b92ffaSHans Petter Selasky *
13*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
14*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
15*d6b92ffaSHans Petter Selasky * conditions are met:
16*d6b92ffaSHans Petter Selasky *
17*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
18*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
19*d6b92ffaSHans Petter Selasky * disclaimer.
20*d6b92ffaSHans Petter Selasky *
21*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
22*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
23*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
24*d6b92ffaSHans Petter Selasky * provided with the distribution.
25*d6b92ffaSHans Petter Selasky *
26*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33*d6b92ffaSHans Petter Selasky * SOFTWARE.
34*d6b92ffaSHans Petter Selasky *
35*d6b92ffaSHans Petter Selasky */
36*d6b92ffaSHans Petter Selasky
37*d6b92ffaSHans Petter Selasky /*
38*d6b92ffaSHans Petter Selasky * Abstract:
39*d6b92ffaSHans Petter Selasky * Implementation of osm_vl15_t.
40*d6b92ffaSHans Petter Selasky * This object represents the VL15 Interface object.
41*d6b92ffaSHans Petter Selasky * This object is part of the opensm family of objects.
42*d6b92ffaSHans Petter Selasky */
43*d6b92ffaSHans Petter Selasky
44*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
45*d6b92ffaSHans Petter Selasky # include <config.h>
46*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */
47*d6b92ffaSHans Petter Selasky
48*d6b92ffaSHans Petter Selasky #include <string.h>
49*d6b92ffaSHans Petter Selasky #include <iba/ib_types.h>
50*d6b92ffaSHans Petter Selasky #include <complib/cl_thread.h>
51*d6b92ffaSHans Petter Selasky #include <opensm/osm_file_ids.h>
52*d6b92ffaSHans Petter Selasky #define FILE_ID OSM_FILE_VL15INTF_C
53*d6b92ffaSHans Petter Selasky #include <vendor/osm_vendor_api.h>
54*d6b92ffaSHans Petter Selasky #include <opensm/osm_vl15intf.h>
55*d6b92ffaSHans Petter Selasky #include <opensm/osm_madw.h>
56*d6b92ffaSHans Petter Selasky #include <opensm/osm_log.h>
57*d6b92ffaSHans Petter Selasky #include <opensm/osm_helper.h>
58*d6b92ffaSHans Petter Selasky
vl15_send_mad(osm_vl15_t * p_vl,osm_madw_t * p_madw)59*d6b92ffaSHans Petter Selasky static void vl15_send_mad(osm_vl15_t * p_vl, osm_madw_t * p_madw)
60*d6b92ffaSHans Petter Selasky {
61*d6b92ffaSHans Petter Selasky ib_api_status_t status;
62*d6b92ffaSHans Petter Selasky boolean_t resp_expected = p_madw->resp_expected;
63*d6b92ffaSHans Petter Selasky ib_smp_t * p_smp;
64*d6b92ffaSHans Petter Selasky ib_net16_t attr_id;
65*d6b92ffaSHans Petter Selasky uint8_t method;
66*d6b92ffaSHans Petter Selasky
67*d6b92ffaSHans Petter Selasky p_smp = osm_madw_get_smp_ptr(p_madw);
68*d6b92ffaSHans Petter Selasky method = p_smp->method;
69*d6b92ffaSHans Petter Selasky attr_id = p_smp->attr_id;
70*d6b92ffaSHans Petter Selasky
71*d6b92ffaSHans Petter Selasky /*
72*d6b92ffaSHans Petter Selasky Non-response-expected mads are not throttled on the wire
73*d6b92ffaSHans Petter Selasky since we can have no confirmation that they arrived
74*d6b92ffaSHans Petter Selasky at their destination.
75*d6b92ffaSHans Petter Selasky */
76*d6b92ffaSHans Petter Selasky if (resp_expected)
77*d6b92ffaSHans Petter Selasky /*
78*d6b92ffaSHans Petter Selasky Note that other threads may not see the response MAD
79*d6b92ffaSHans Petter Selasky arrive before send() even returns.
80*d6b92ffaSHans Petter Selasky In that case, the wire count would temporarily go negative.
81*d6b92ffaSHans Petter Selasky To avoid this confusion, preincrement the counts on the
82*d6b92ffaSHans Petter Selasky assumption that send() will succeed.
83*d6b92ffaSHans Petter Selasky */
84*d6b92ffaSHans Petter Selasky cl_atomic_inc(&p_vl->p_stats->qp0_mads_outstanding_on_wire);
85*d6b92ffaSHans Petter Selasky else
86*d6b92ffaSHans Petter Selasky cl_atomic_inc(&p_vl->p_stats->qp0_unicasts_sent);
87*d6b92ffaSHans Petter Selasky
88*d6b92ffaSHans Petter Selasky cl_atomic_inc(&p_vl->p_stats->qp0_mads_sent);
89*d6b92ffaSHans Petter Selasky
90*d6b92ffaSHans Petter Selasky status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
91*d6b92ffaSHans Petter Selasky p_madw, p_madw->resp_expected);
92*d6b92ffaSHans Petter Selasky
93*d6b92ffaSHans Petter Selasky if (status == IB_SUCCESS) {
94*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
95*d6b92ffaSHans Petter Selasky "%u QP0 MADs on wire, %u outstanding, "
96*d6b92ffaSHans Petter Selasky "%u unicasts sent, %u total sent\n",
97*d6b92ffaSHans Petter Selasky p_vl->p_stats->qp0_mads_outstanding_on_wire,
98*d6b92ffaSHans Petter Selasky p_vl->p_stats->qp0_mads_outstanding,
99*d6b92ffaSHans Petter Selasky p_vl->p_stats->qp0_unicasts_sent,
100*d6b92ffaSHans Petter Selasky p_vl->p_stats->qp0_mads_sent);
101*d6b92ffaSHans Petter Selasky return;
102*d6b92ffaSHans Petter Selasky }
103*d6b92ffaSHans Petter Selasky
104*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E03: "
105*d6b92ffaSHans Petter Selasky "MAD send failed (%s)\n", ib_get_err_str(status));
106*d6b92ffaSHans Petter Selasky
107*d6b92ffaSHans Petter Selasky /*
108*d6b92ffaSHans Petter Selasky The MAD was never successfully sent, so
109*d6b92ffaSHans Petter Selasky fix up the pre-incremented count values.
110*d6b92ffaSHans Petter Selasky */
111*d6b92ffaSHans Petter Selasky
112*d6b92ffaSHans Petter Selasky /* Decrement qp0_mads_sent that were incremented in the code above.
113*d6b92ffaSHans Petter Selasky qp0_mads_outstanding will be decremented by send error callback
114*d6b92ffaSHans Petter Selasky (called by osm_vendor_send() */
115*d6b92ffaSHans Petter Selasky cl_atomic_dec(&p_vl->p_stats->qp0_mads_sent);
116*d6b92ffaSHans Petter Selasky if (!resp_expected) {
117*d6b92ffaSHans Petter Selasky cl_atomic_dec(&p_vl->p_stats->qp0_unicasts_sent);
118*d6b92ffaSHans Petter Selasky return;
119*d6b92ffaSHans Petter Selasky }
120*d6b92ffaSHans Petter Selasky
121*d6b92ffaSHans Petter Selasky /* need to cause heavy-sweep if resp_expected MAD sending failed */
122*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E04: "
123*d6b92ffaSHans Petter Selasky "%s method failed for attribute 0x%X (%s)\n",
124*d6b92ffaSHans Petter Selasky method == IB_MAD_METHOD_SET ? "SET" : "GET",
125*d6b92ffaSHans Petter Selasky cl_ntoh16(attr_id), ib_get_sm_attr_str(attr_id));
126*d6b92ffaSHans Petter Selasky
127*d6b92ffaSHans Petter Selasky p_vl->p_subn->subnet_initialization_error = TRUE;
128*d6b92ffaSHans Petter Selasky
129*d6b92ffaSHans Petter Selasky }
130*d6b92ffaSHans Petter Selasky
vl15_poller(IN void * p_ptr)131*d6b92ffaSHans Petter Selasky static void vl15_poller(IN void *p_ptr)
132*d6b92ffaSHans Petter Selasky {
133*d6b92ffaSHans Petter Selasky ib_api_status_t status;
134*d6b92ffaSHans Petter Selasky osm_madw_t *p_madw;
135*d6b92ffaSHans Petter Selasky osm_vl15_t *p_vl = p_ptr;
136*d6b92ffaSHans Petter Selasky cl_qlist_t *p_fifo;
137*d6b92ffaSHans Petter Selasky int32_t max_smps = p_vl->max_wire_smps;
138*d6b92ffaSHans Petter Selasky int32_t max_smps2 = p_vl->max_wire_smps2;
139*d6b92ffaSHans Petter Selasky
140*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_vl->p_log);
141*d6b92ffaSHans Petter Selasky
142*d6b92ffaSHans Petter Selasky if (p_vl->thread_state == OSM_THREAD_STATE_NONE)
143*d6b92ffaSHans Petter Selasky p_vl->thread_state = OSM_THREAD_STATE_RUN;
144*d6b92ffaSHans Petter Selasky
145*d6b92ffaSHans Petter Selasky while (p_vl->thread_state == OSM_THREAD_STATE_RUN) {
146*d6b92ffaSHans Petter Selasky /*
147*d6b92ffaSHans Petter Selasky Start servicing the FIFOs by pulling off MAD wrappers
148*d6b92ffaSHans Petter Selasky and passing them to the transport interface.
149*d6b92ffaSHans Petter Selasky There are lots of corner cases here so tread carefully.
150*d6b92ffaSHans Petter Selasky
151*d6b92ffaSHans Petter Selasky The unicast FIFO has priority, since somebody is waiting
152*d6b92ffaSHans Petter Selasky for a timely response.
153*d6b92ffaSHans Petter Selasky */
154*d6b92ffaSHans Petter Selasky cl_spinlock_acquire(&p_vl->lock);
155*d6b92ffaSHans Petter Selasky
156*d6b92ffaSHans Petter Selasky if (cl_qlist_count(&p_vl->ufifo) != 0)
157*d6b92ffaSHans Petter Selasky p_fifo = &p_vl->ufifo;
158*d6b92ffaSHans Petter Selasky else
159*d6b92ffaSHans Petter Selasky p_fifo = &p_vl->rfifo;
160*d6b92ffaSHans Petter Selasky
161*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(p_fifo);
162*d6b92ffaSHans Petter Selasky
163*d6b92ffaSHans Petter Selasky cl_spinlock_release(&p_vl->lock);
164*d6b92ffaSHans Petter Selasky
165*d6b92ffaSHans Petter Selasky if (p_madw != (osm_madw_t *) cl_qlist_end(p_fifo)) {
166*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
167*d6b92ffaSHans Petter Selasky "Servicing p_madw = %p\n", p_madw);
168*d6b92ffaSHans Petter Selasky if (OSM_LOG_IS_ACTIVE_V2(p_vl->p_log, OSM_LOG_FRAMES))
169*d6b92ffaSHans Petter Selasky osm_dump_dr_smp_v2(p_vl->p_log,
170*d6b92ffaSHans Petter Selasky osm_madw_get_smp_ptr(p_madw),
171*d6b92ffaSHans Petter Selasky FILE_ID, OSM_LOG_FRAMES);
172*d6b92ffaSHans Petter Selasky
173*d6b92ffaSHans Petter Selasky vl15_send_mad(p_vl, p_madw);
174*d6b92ffaSHans Petter Selasky } else
175*d6b92ffaSHans Petter Selasky /*
176*d6b92ffaSHans Petter Selasky The VL15 FIFO is empty, so we have nothing left to do.
177*d6b92ffaSHans Petter Selasky */
178*d6b92ffaSHans Petter Selasky status = cl_event_wait_on(&p_vl->signal,
179*d6b92ffaSHans Petter Selasky EVENT_NO_TIMEOUT, TRUE);
180*d6b92ffaSHans Petter Selasky
181*d6b92ffaSHans Petter Selasky while (p_vl->p_stats->qp0_mads_outstanding_on_wire >= max_smps &&
182*d6b92ffaSHans Petter Selasky p_vl->thread_state == OSM_THREAD_STATE_RUN) {
183*d6b92ffaSHans Petter Selasky status = cl_event_wait_on(&p_vl->signal,
184*d6b92ffaSHans Petter Selasky p_vl->max_smps_timeout,
185*d6b92ffaSHans Petter Selasky TRUE);
186*d6b92ffaSHans Petter Selasky if (status == CL_TIMEOUT) {
187*d6b92ffaSHans Petter Selasky if (max_smps < max_smps2)
188*d6b92ffaSHans Petter Selasky max_smps++;
189*d6b92ffaSHans Petter Selasky break;
190*d6b92ffaSHans Petter Selasky } else if (status != CL_SUCCESS) {
191*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E02: "
192*d6b92ffaSHans Petter Selasky "Event wait failed (%s)\n",
193*d6b92ffaSHans Petter Selasky CL_STATUS_MSG(status));
194*d6b92ffaSHans Petter Selasky break;
195*d6b92ffaSHans Petter Selasky }
196*d6b92ffaSHans Petter Selasky max_smps = p_vl->max_wire_smps;
197*d6b92ffaSHans Petter Selasky }
198*d6b92ffaSHans Petter Selasky }
199*d6b92ffaSHans Petter Selasky
200*d6b92ffaSHans Petter Selasky /*
201*d6b92ffaSHans Petter Selasky since we abort immediately when the state != OSM_THREAD_STATE_RUN
202*d6b92ffaSHans Petter Selasky we might have some mads on the queues. After the thread exits
203*d6b92ffaSHans Petter Selasky the vl15 destroy routine should put these mads back...
204*d6b92ffaSHans Petter Selasky */
205*d6b92ffaSHans Petter Selasky
206*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_vl->p_log);
207*d6b92ffaSHans Petter Selasky }
208*d6b92ffaSHans Petter Selasky
osm_vl15_construct(IN osm_vl15_t * p_vl)209*d6b92ffaSHans Petter Selasky void osm_vl15_construct(IN osm_vl15_t * p_vl)
210*d6b92ffaSHans Petter Selasky {
211*d6b92ffaSHans Petter Selasky memset(p_vl, 0, sizeof(*p_vl));
212*d6b92ffaSHans Petter Selasky p_vl->state = OSM_VL15_STATE_INIT;
213*d6b92ffaSHans Petter Selasky p_vl->thread_state = OSM_THREAD_STATE_NONE;
214*d6b92ffaSHans Petter Selasky cl_event_construct(&p_vl->signal);
215*d6b92ffaSHans Petter Selasky cl_spinlock_construct(&p_vl->lock);
216*d6b92ffaSHans Petter Selasky cl_qlist_init(&p_vl->rfifo);
217*d6b92ffaSHans Petter Selasky cl_qlist_init(&p_vl->ufifo);
218*d6b92ffaSHans Petter Selasky cl_thread_construct(&p_vl->poller);
219*d6b92ffaSHans Petter Selasky }
220*d6b92ffaSHans Petter Selasky
osm_vl15_destroy(IN osm_vl15_t * p_vl,IN struct osm_mad_pool * p_pool)221*d6b92ffaSHans Petter Selasky void osm_vl15_destroy(IN osm_vl15_t * p_vl, IN struct osm_mad_pool *p_pool)
222*d6b92ffaSHans Petter Selasky {
223*d6b92ffaSHans Petter Selasky osm_madw_t *p_madw;
224*d6b92ffaSHans Petter Selasky
225*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_vl->p_log);
226*d6b92ffaSHans Petter Selasky
227*d6b92ffaSHans Petter Selasky /*
228*d6b92ffaSHans Petter Selasky Signal our threads that we're leaving.
229*d6b92ffaSHans Petter Selasky */
230*d6b92ffaSHans Petter Selasky p_vl->thread_state = OSM_THREAD_STATE_EXIT;
231*d6b92ffaSHans Petter Selasky
232*d6b92ffaSHans Petter Selasky /*
233*d6b92ffaSHans Petter Selasky Don't trigger unless event has been initialized.
234*d6b92ffaSHans Petter Selasky Destroy the thread before we tear down the other objects.
235*d6b92ffaSHans Petter Selasky */
236*d6b92ffaSHans Petter Selasky if (p_vl->state != OSM_VL15_STATE_INIT)
237*d6b92ffaSHans Petter Selasky cl_event_signal(&p_vl->signal);
238*d6b92ffaSHans Petter Selasky
239*d6b92ffaSHans Petter Selasky cl_thread_destroy(&p_vl->poller);
240*d6b92ffaSHans Petter Selasky
241*d6b92ffaSHans Petter Selasky /*
242*d6b92ffaSHans Petter Selasky Return the outstanding messages to the pool
243*d6b92ffaSHans Petter Selasky */
244*d6b92ffaSHans Petter Selasky
245*d6b92ffaSHans Petter Selasky cl_spinlock_acquire(&p_vl->lock);
246*d6b92ffaSHans Petter Selasky
247*d6b92ffaSHans Petter Selasky while (!cl_is_qlist_empty(&p_vl->rfifo)) {
248*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo);
249*d6b92ffaSHans Petter Selasky osm_mad_pool_put(p_pool, p_madw);
250*d6b92ffaSHans Petter Selasky }
251*d6b92ffaSHans Petter Selasky while (!cl_is_qlist_empty(&p_vl->ufifo)) {
252*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo);
253*d6b92ffaSHans Petter Selasky osm_mad_pool_put(p_pool, p_madw);
254*d6b92ffaSHans Petter Selasky }
255*d6b92ffaSHans Petter Selasky
256*d6b92ffaSHans Petter Selasky cl_spinlock_release(&p_vl->lock);
257*d6b92ffaSHans Petter Selasky
258*d6b92ffaSHans Petter Selasky cl_event_destroy(&p_vl->signal);
259*d6b92ffaSHans Petter Selasky p_vl->state = OSM_VL15_STATE_INIT;
260*d6b92ffaSHans Petter Selasky cl_spinlock_destroy(&p_vl->lock);
261*d6b92ffaSHans Petter Selasky
262*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_vl->p_log);
263*d6b92ffaSHans Petter Selasky }
264*d6b92ffaSHans Petter Selasky
osm_vl15_init(IN osm_vl15_t * p_vl,IN osm_vendor_t * p_vend,IN osm_log_t * p_log,IN osm_stats_t * p_stats,IN osm_subn_t * p_subn,IN int32_t max_wire_smps,IN int32_t max_wire_smps2,IN uint32_t max_smps_timeout)265*d6b92ffaSHans Petter Selasky ib_api_status_t osm_vl15_init(IN osm_vl15_t * p_vl, IN osm_vendor_t * p_vend,
266*d6b92ffaSHans Petter Selasky IN osm_log_t * p_log, IN osm_stats_t * p_stats,
267*d6b92ffaSHans Petter Selasky IN osm_subn_t * p_subn,
268*d6b92ffaSHans Petter Selasky IN int32_t max_wire_smps,
269*d6b92ffaSHans Petter Selasky IN int32_t max_wire_smps2,
270*d6b92ffaSHans Petter Selasky IN uint32_t max_smps_timeout)
271*d6b92ffaSHans Petter Selasky {
272*d6b92ffaSHans Petter Selasky ib_api_status_t status = IB_SUCCESS;
273*d6b92ffaSHans Petter Selasky
274*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_log);
275*d6b92ffaSHans Petter Selasky
276*d6b92ffaSHans Petter Selasky p_vl->p_vend = p_vend;
277*d6b92ffaSHans Petter Selasky p_vl->p_log = p_log;
278*d6b92ffaSHans Petter Selasky p_vl->p_stats = p_stats;
279*d6b92ffaSHans Petter Selasky p_vl->p_subn = p_subn;
280*d6b92ffaSHans Petter Selasky p_vl->max_wire_smps = max_wire_smps;
281*d6b92ffaSHans Petter Selasky p_vl->max_wire_smps2 = max_wire_smps2;
282*d6b92ffaSHans Petter Selasky p_vl->max_smps_timeout = max_wire_smps < max_wire_smps2 ?
283*d6b92ffaSHans Petter Selasky max_smps_timeout : EVENT_NO_TIMEOUT;
284*d6b92ffaSHans Petter Selasky
285*d6b92ffaSHans Petter Selasky status = cl_event_init(&p_vl->signal, FALSE);
286*d6b92ffaSHans Petter Selasky if (status != IB_SUCCESS)
287*d6b92ffaSHans Petter Selasky goto Exit;
288*d6b92ffaSHans Petter Selasky
289*d6b92ffaSHans Petter Selasky p_vl->state = OSM_VL15_STATE_READY;
290*d6b92ffaSHans Petter Selasky
291*d6b92ffaSHans Petter Selasky status = cl_spinlock_init(&p_vl->lock);
292*d6b92ffaSHans Petter Selasky if (status != IB_SUCCESS)
293*d6b92ffaSHans Petter Selasky goto Exit;
294*d6b92ffaSHans Petter Selasky
295*d6b92ffaSHans Petter Selasky /*
296*d6b92ffaSHans Petter Selasky Initialize the thread after all other dependent objects
297*d6b92ffaSHans Petter Selasky have been initialized.
298*d6b92ffaSHans Petter Selasky */
299*d6b92ffaSHans Petter Selasky status = cl_thread_init(&p_vl->poller, vl15_poller, p_vl,
300*d6b92ffaSHans Petter Selasky "opensm poller");
301*d6b92ffaSHans Petter Selasky Exit:
302*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_log);
303*d6b92ffaSHans Petter Selasky return status;
304*d6b92ffaSHans Petter Selasky }
305*d6b92ffaSHans Petter Selasky
osm_vl15_poll(IN osm_vl15_t * p_vl)306*d6b92ffaSHans Petter Selasky void osm_vl15_poll(IN osm_vl15_t * p_vl)
307*d6b92ffaSHans Petter Selasky {
308*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_vl->p_log);
309*d6b92ffaSHans Petter Selasky
310*d6b92ffaSHans Petter Selasky CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY);
311*d6b92ffaSHans Petter Selasky
312*d6b92ffaSHans Petter Selasky /*
313*d6b92ffaSHans Petter Selasky If we have room for more VL15 MADs on the wire,
314*d6b92ffaSHans Petter Selasky then signal the poller thread.
315*d6b92ffaSHans Petter Selasky
316*d6b92ffaSHans Petter Selasky This is not an airtight check, since the poller thread
317*d6b92ffaSHans Petter Selasky could be just about to send another MAD as we signal
318*d6b92ffaSHans Petter Selasky the event here. To cover this rare case, the poller
319*d6b92ffaSHans Petter Selasky thread checks for a spurious wake-up.
320*d6b92ffaSHans Petter Selasky */
321*d6b92ffaSHans Petter Selasky if (p_vl->p_stats->qp0_mads_outstanding_on_wire <
322*d6b92ffaSHans Petter Selasky (int32_t) p_vl->max_wire_smps) {
323*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
324*d6b92ffaSHans Petter Selasky "Signalling poller thread\n");
325*d6b92ffaSHans Petter Selasky cl_event_signal(&p_vl->signal);
326*d6b92ffaSHans Petter Selasky }
327*d6b92ffaSHans Petter Selasky
328*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_vl->p_log);
329*d6b92ffaSHans Petter Selasky }
330*d6b92ffaSHans Petter Selasky
osm_vl15_post(IN osm_vl15_t * p_vl,IN osm_madw_t * p_madw)331*d6b92ffaSHans Petter Selasky void osm_vl15_post(IN osm_vl15_t * p_vl, IN osm_madw_t * p_madw)
332*d6b92ffaSHans Petter Selasky {
333*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_vl->p_log);
334*d6b92ffaSHans Petter Selasky
335*d6b92ffaSHans Petter Selasky CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY);
336*d6b92ffaSHans Petter Selasky
337*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG, "Posting p_madw = %p\n", p_madw);
338*d6b92ffaSHans Petter Selasky
339*d6b92ffaSHans Petter Selasky /*
340*d6b92ffaSHans Petter Selasky Determine in which fifo to place the pending madw.
341*d6b92ffaSHans Petter Selasky */
342*d6b92ffaSHans Petter Selasky cl_spinlock_acquire(&p_vl->lock);
343*d6b92ffaSHans Petter Selasky if (p_madw->resp_expected == TRUE) {
344*d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(&p_vl->rfifo, &p_madw->list_item);
345*d6b92ffaSHans Petter Selasky osm_stats_inc_qp0_outstanding(p_vl->p_stats);
346*d6b92ffaSHans Petter Selasky } else
347*d6b92ffaSHans Petter Selasky cl_qlist_insert_tail(&p_vl->ufifo, &p_madw->list_item);
348*d6b92ffaSHans Petter Selasky cl_spinlock_release(&p_vl->lock);
349*d6b92ffaSHans Petter Selasky
350*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
351*d6b92ffaSHans Petter Selasky "%u QP0 MADs on wire, %u QP0 MADs outstanding\n",
352*d6b92ffaSHans Petter Selasky p_vl->p_stats->qp0_mads_outstanding_on_wire,
353*d6b92ffaSHans Petter Selasky p_vl->p_stats->qp0_mads_outstanding);
354*d6b92ffaSHans Petter Selasky
355*d6b92ffaSHans Petter Selasky osm_vl15_poll(p_vl);
356*d6b92ffaSHans Petter Selasky
357*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_vl->p_log);
358*d6b92ffaSHans Petter Selasky }
359*d6b92ffaSHans Petter Selasky
osm_vl15_shutdown(IN osm_vl15_t * p_vl,IN osm_mad_pool_t * p_mad_pool)360*d6b92ffaSHans Petter Selasky void osm_vl15_shutdown(IN osm_vl15_t * p_vl, IN osm_mad_pool_t * p_mad_pool)
361*d6b92ffaSHans Petter Selasky {
362*d6b92ffaSHans Petter Selasky osm_madw_t *p_madw;
363*d6b92ffaSHans Petter Selasky
364*d6b92ffaSHans Petter Selasky OSM_LOG_ENTER(p_vl->p_log);
365*d6b92ffaSHans Petter Selasky
366*d6b92ffaSHans Petter Selasky /* we only should get here after the VL15 interface was initialized */
367*d6b92ffaSHans Petter Selasky CL_ASSERT(p_vl->state == OSM_VL15_STATE_READY);
368*d6b92ffaSHans Petter Selasky
369*d6b92ffaSHans Petter Selasky /* grab a lock on the object */
370*d6b92ffaSHans Petter Selasky cl_spinlock_acquire(&p_vl->lock);
371*d6b92ffaSHans Petter Selasky
372*d6b92ffaSHans Petter Selasky /* go over all outstanding MADs and retire their transactions */
373*d6b92ffaSHans Petter Selasky
374*d6b92ffaSHans Petter Selasky /* first we handle the list of response MADs */
375*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo);
376*d6b92ffaSHans Petter Selasky while (p_madw != (osm_madw_t *) cl_qlist_end(&p_vl->ufifo)) {
377*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
378*d6b92ffaSHans Petter Selasky "Releasing Response p_madw = %p\n", p_madw);
379*d6b92ffaSHans Petter Selasky
380*d6b92ffaSHans Petter Selasky osm_mad_pool_put(p_mad_pool, p_madw);
381*d6b92ffaSHans Petter Selasky
382*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->ufifo);
383*d6b92ffaSHans Petter Selasky }
384*d6b92ffaSHans Petter Selasky
385*d6b92ffaSHans Petter Selasky /* Request MADs we send out */
386*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo);
387*d6b92ffaSHans Petter Selasky while (p_madw != (osm_madw_t *) cl_qlist_end(&p_vl->rfifo)) {
388*d6b92ffaSHans Petter Selasky OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
389*d6b92ffaSHans Petter Selasky "Releasing Request p_madw = %p\n", p_madw);
390*d6b92ffaSHans Petter Selasky
391*d6b92ffaSHans Petter Selasky osm_mad_pool_put(p_mad_pool, p_madw);
392*d6b92ffaSHans Petter Selasky osm_stats_dec_qp0_outstanding(p_vl->p_stats);
393*d6b92ffaSHans Petter Selasky
394*d6b92ffaSHans Petter Selasky p_madw = (osm_madw_t *) cl_qlist_remove_head(&p_vl->rfifo);
395*d6b92ffaSHans Petter Selasky }
396*d6b92ffaSHans Petter Selasky
397*d6b92ffaSHans Petter Selasky /* free the lock */
398*d6b92ffaSHans Petter Selasky cl_spinlock_release(&p_vl->lock);
399*d6b92ffaSHans Petter Selasky
400*d6b92ffaSHans Petter Selasky OSM_LOG_EXIT(p_vl->p_log);
401*d6b92ffaSHans Petter Selasky }
402