xref: /freebsd/contrib/ofed/opensm/opensm/osm_vl15intf.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
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