1*5d5562f5SEiji Ota /*
2*5d5562f5SEiji Ota  * CDDL HEADER START
3*5d5562f5SEiji Ota  *
4*5d5562f5SEiji Ota  * The contents of this file are subject to the terms of the
5*5d5562f5SEiji Ota  * Common Development and Distribution License (the "License").
6*5d5562f5SEiji Ota  * You may not use this file except in compliance with the License.
7*5d5562f5SEiji Ota  *
8*5d5562f5SEiji Ota  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5d5562f5SEiji Ota  * or http://www.opensolaris.org/os/licensing.
10*5d5562f5SEiji Ota  * See the License for the specific language governing permissions
11*5d5562f5SEiji Ota  * and limitations under the License.
12*5d5562f5SEiji Ota  *
13*5d5562f5SEiji Ota  * When distributing Covered Code, include this CDDL HEADER in each
14*5d5562f5SEiji Ota  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5d5562f5SEiji Ota  * If applicable, add the following below this CDDL HEADER, with the
16*5d5562f5SEiji Ota  * fields enclosed by brackets "[]" replaced with your own identifying
17*5d5562f5SEiji Ota  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5d5562f5SEiji Ota  *
19*5d5562f5SEiji Ota  * CDDL HEADER END
20*5d5562f5SEiji Ota  */
21*5d5562f5SEiji Ota /*
22*5d5562f5SEiji Ota  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23*5d5562f5SEiji Ota  */
24*5d5562f5SEiji Ota #include <sys/ib/clients/rdsv3/ib.h>
25*5d5562f5SEiji Ota #include <sys/ib/clients/rdsv3/rdsv3_af_thr_impl.h>
26*5d5562f5SEiji Ota #include <sys/ib/clients/rdsv3/rdsv3_debug.h>
27*5d5562f5SEiji Ota 
28*5d5562f5SEiji Ota extern pri_t maxclsyspri;
29*5d5562f5SEiji Ota extern kmutex_t cpu_lock;
30*5d5562f5SEiji Ota 
31*5d5562f5SEiji Ota int rdsv3_enable_snd_cq = 0;
32*5d5562f5SEiji Ota int rdsv3_intr_line_up_mode = 0;
33*5d5562f5SEiji Ota static kmutex_t rdsv3_cpuid_pool_lock;
34*5d5562f5SEiji Ota 
35*5d5562f5SEiji Ota void
rdsv3_af_init(dev_info_t * dip)36*5d5562f5SEiji Ota rdsv3_af_init(dev_info_t *dip)
37*5d5562f5SEiji Ota {
38*5d5562f5SEiji Ota 	int i;
39*5d5562f5SEiji Ota 	cpu_t *cp;
40*5d5562f5SEiji Ota 	int *msix;
41*5d5562f5SEiji Ota 	uint_t nmsix;
42*5d5562f5SEiji Ota 	extern int ncpus;
43*5d5562f5SEiji Ota 
44*5d5562f5SEiji Ota 	mutex_init(&rdsv3_cpuid_pool_lock, NULL, MUTEX_DEFAULT, NULL);
45*5d5562f5SEiji Ota 	if (ncpus < RDSV3_CPUID_POOL_MAX)
46*5d5562f5SEiji Ota 		rdsv3_cpuid_pool_cnt = ncpus;
47*5d5562f5SEiji Ota 	else
48*5d5562f5SEiji Ota 		rdsv3_cpuid_pool_cnt = RDSV3_CPUID_POOL_MAX;
49*5d5562f5SEiji Ota 
50*5d5562f5SEiji Ota 	/* hold cpu_lock before calling cpu_get and cpu_is_online */
51*5d5562f5SEiji Ota 	mutex_enter(&cpu_lock);
52*5d5562f5SEiji Ota 	for (i = 0; i < rdsv3_cpuid_pool_cnt; i++) {
53*5d5562f5SEiji Ota 		cp = cpu_get((processorid_t)i);
54*5d5562f5SEiji Ota 		if (cp == NULL || !cpu_is_online(cp))
55*5d5562f5SEiji Ota 			rdsv3_cpuid_pool[i] = RDSV3_CPUFLAGS_OFF;
56*5d5562f5SEiji Ota 		else
57*5d5562f5SEiji Ota 			rdsv3_cpuid_pool[i] = RDSV3_CPUFLAGS_ON;
58*5d5562f5SEiji Ota 	}
59*5d5562f5SEiji Ota 	mutex_exit(&cpu_lock);
60*5d5562f5SEiji Ota 
61*5d5562f5SEiji Ota 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
62*5d5562f5SEiji Ota 	    "HcaMsix", (int **)&msix, &nmsix) == DDI_PROP_SUCCESS) {
63*5d5562f5SEiji Ota 		/* remove the hca MSI-x interrupt cpu's */
64*5d5562f5SEiji Ota 		for (i = 0; i < nmsix; i++) {
65*5d5562f5SEiji Ota 			rdsv3_cpuid_pool[msix[i]] |= RDSV3_CPUFLAGS_INTR;
66*5d5562f5SEiji Ota 			rdsv3_msix_pool[i] = msix[i];
67*5d5562f5SEiji Ota 		}
68*5d5562f5SEiji Ota 		rdsv3_msix_pool_cnt = nmsix;
69*5d5562f5SEiji Ota 		ddi_prop_free(msix);
70*5d5562f5SEiji Ota 	}
71*5d5562f5SEiji Ota 	rdsv3_enable_snd_cq = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
72*5d5562f5SEiji Ota 	    DDI_PROP_DONTPASS, "EnableSendCQ", 0);
73*5d5562f5SEiji Ota 	rdsv3_intr_line_up_mode = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
74*5d5562f5SEiji Ota 	    DDI_PROP_DONTPASS, "IntrLineUpMode", 0);
75*5d5562f5SEiji Ota }
76*5d5562f5SEiji Ota 
77*5d5562f5SEiji Ota static void
rdsv3_af_cpu_assign(rdsv3_af_grp_t * hcagp)78*5d5562f5SEiji Ota rdsv3_af_cpu_assign(rdsv3_af_grp_t *hcagp)
79*5d5562f5SEiji Ota {
80*5d5562f5SEiji Ota 	int i, j, k, idx;
81*5d5562f5SEiji Ota 
82*5d5562f5SEiji Ota 	RDSV3_DPRINTF2("rdsv3_af_cpu_assign", "hcagp %p", hcagp);
83*5d5562f5SEiji Ota 
84*5d5562f5SEiji Ota 	mutex_enter(&rdsv3_cpuid_pool_lock);
85*5d5562f5SEiji Ota 	for (i = 0; i < rdsv3_cpuid_pool_cnt; i++) {
86*5d5562f5SEiji Ota 		if (!(rdsv3_cpuid_pool[i] & (RDSV3_CPUFLAGS_UNAVAIL |
87*5d5562f5SEiji Ota 		    RDSV3_CPUFLAGS_ASSIGNED | RDSV3_CPUFLAGS_HCA))) {
88*5d5562f5SEiji Ota 			rdsv3_cpuid_pool[i] |= RDSV3_CPUFLAGS_HCA;
89*5d5562f5SEiji Ota 			hcagp->g_hca_cpuid = i;
90*5d5562f5SEiji Ota 			break;
91*5d5562f5SEiji Ota 		}
92*5d5562f5SEiji Ota 		/* share an assigned cpu */
93*5d5562f5SEiji Ota 		for (j = 0; j < rdsv3_cpuid_pool_cnt; j++) {
94*5d5562f5SEiji Ota 			if (!(rdsv3_cpuid_pool[j] & (RDSV3_CPUFLAGS_UNAVAIL |
95*5d5562f5SEiji Ota 			    RDSV3_CPUFLAGS_HCA))) {
96*5d5562f5SEiji Ota 				hcagp->g_hca_cpuid = j;
97*5d5562f5SEiji Ota 				break;
98*5d5562f5SEiji Ota 			}
99*5d5562f5SEiji Ota 		}
100*5d5562f5SEiji Ota 		/* if the code comes down here, cpu 0 will be used */
101*5d5562f5SEiji Ota 	}
102*5d5562f5SEiji Ota 
103*5d5562f5SEiji Ota 	for (j = 0; j < RDSV3_AFT_CONN_CPU_POOL; j++) {
104*5d5562f5SEiji Ota 		/* initialize to be an out-of-bound cpuid, no binding */
105*5d5562f5SEiji Ota 		hcagp->g_conn_cpuid_pool[j] = rdsv3_cpuid_pool_cnt;
106*5d5562f5SEiji Ota 		for (i = 0; i < rdsv3_cpuid_pool_cnt; i++) {
107*5d5562f5SEiji Ota 			if (!(rdsv3_cpuid_pool[i] & (RDSV3_CPUFLAGS_UNAVAIL |
108*5d5562f5SEiji Ota 			    RDSV3_CPUFLAGS_ASSIGNED | RDSV3_CPUFLAGS_HCA))) {
109*5d5562f5SEiji Ota 				rdsv3_cpuid_pool[i] |= RDSV3_CPUFLAGS_ASSIGNED;
110*5d5562f5SEiji Ota 				hcagp->g_conn_cpuid_pool[j] = i;
111*5d5562f5SEiji Ota 				break;
112*5d5562f5SEiji Ota 			}
113*5d5562f5SEiji Ota 		}
114*5d5562f5SEiji Ota 		if (i >= rdsv3_cpuid_pool_cnt)
115*5d5562f5SEiji Ota 			break;
116*5d5562f5SEiji Ota 	}
117*5d5562f5SEiji Ota 	if (j >= RDSV3_AFT_CONN_CPU_POOL) {
118*5d5562f5SEiji Ota 		mutex_exit(&rdsv3_cpuid_pool_lock);
119*5d5562f5SEiji Ota 		return;
120*5d5562f5SEiji Ota 	}
121*5d5562f5SEiji Ota 	/* avoid the primary group */
122*5d5562f5SEiji Ota 	for (k = 0, idx = 0; k < 2; k++) {
123*5d5562f5SEiji Ota 		/* search to the start of an hca group */
124*5d5562f5SEiji Ota 		for (i = idx; i < rdsv3_cpuid_pool_cnt; i++) {
125*5d5562f5SEiji Ota 			if (rdsv3_cpuid_pool[i] & RDSV3_CPUFLAGS_HCA) {
126*5d5562f5SEiji Ota 				idx = i + 1;
127*5d5562f5SEiji Ota 				break;
128*5d5562f5SEiji Ota 			}
129*5d5562f5SEiji Ota 		}
130*5d5562f5SEiji Ota 	}
131*5d5562f5SEiji Ota 	/* share an assigned cpu */
132*5d5562f5SEiji Ota 	for (; j < RDSV3_AFT_CONN_CPU_POOL; j++) {
133*5d5562f5SEiji Ota 		for (i = idx; i < rdsv3_cpuid_pool_cnt; i++) {
134*5d5562f5SEiji Ota 			if (!(rdsv3_cpuid_pool[i] & (RDSV3_CPUFLAGS_UNAVAIL |
135*5d5562f5SEiji Ota 			    RDSV3_CPUFLAGS_HCA))) {
136*5d5562f5SEiji Ota 				hcagp->g_conn_cpuid_pool[j] = i;
137*5d5562f5SEiji Ota 				idx = i + 1;
138*5d5562f5SEiji Ota 				break;
139*5d5562f5SEiji Ota 			}
140*5d5562f5SEiji Ota 		}
141*5d5562f5SEiji Ota 	}
142*5d5562f5SEiji Ota 	mutex_exit(&rdsv3_cpuid_pool_lock);
143*5d5562f5SEiji Ota }
144*5d5562f5SEiji Ota 
145*5d5562f5SEiji Ota rdsv3_af_grp_t *
rdsv3_af_grp_create(ibt_hca_hdl_t hca,uint64_t id)146*5d5562f5SEiji Ota rdsv3_af_grp_create(ibt_hca_hdl_t hca, uint64_t id)
147*5d5562f5SEiji Ota {
148*5d5562f5SEiji Ota 	char name[128];
149*5d5562f5SEiji Ota 	ibt_cq_sched_attr_t cq_sched_attr;
150*5d5562f5SEiji Ota 	ibt_status_t status;
151*5d5562f5SEiji Ota 	rdsv3_af_grp_t *hcagp;
152*5d5562f5SEiji Ota 	uint64_t l_id = id;
153*5d5562f5SEiji Ota 
154*5d5562f5SEiji Ota 	hcagp = kmem_zalloc(sizeof (*hcagp), KM_NOSLEEP);
155*5d5562f5SEiji Ota 	if (!hcagp)
156*5d5562f5SEiji Ota 		return (NULL);
157*5d5562f5SEiji Ota 	hcagp->g_hca_hdl = hca;
158*5d5562f5SEiji Ota 
159*5d5562f5SEiji Ota 	rdsv3_af_cpu_assign(hcagp);
160*5d5562f5SEiji Ota 	return (hcagp);
161*5d5562f5SEiji Ota }
162*5d5562f5SEiji Ota 
163*5d5562f5SEiji Ota void
rdsv3_af_grp_destroy(rdsv3_af_grp_t * hcagp)164*5d5562f5SEiji Ota rdsv3_af_grp_destroy(rdsv3_af_grp_t *hcagp)
165*5d5562f5SEiji Ota {
166*5d5562f5SEiji Ota 	if (hcagp == NULL)
167*5d5562f5SEiji Ota 		return;
168*5d5562f5SEiji Ota 
169*5d5562f5SEiji Ota 	kmem_free(hcagp, sizeof (*hcagp));
170*5d5562f5SEiji Ota }
171*5d5562f5SEiji Ota 
172*5d5562f5SEiji Ota void
rdsv3_af_grp_draw(rdsv3_af_grp_t * hcagp)173*5d5562f5SEiji Ota rdsv3_af_grp_draw(rdsv3_af_grp_t *hcagp)
174*5d5562f5SEiji Ota {
175*5d5562f5SEiji Ota 	rdsv3_af_grp_t *l_hcagp = hcagp;
176*5d5562f5SEiji Ota }
177*5d5562f5SEiji Ota 
178*5d5562f5SEiji Ota ibt_sched_hdl_t
rdsv3_af_grp_get_sched(rdsv3_af_grp_t * hcagp)179*5d5562f5SEiji Ota rdsv3_af_grp_get_sched(rdsv3_af_grp_t *hcagp)
180*5d5562f5SEiji Ota {
181*5d5562f5SEiji Ota 	return (hcagp->g_sched_hdl);
182*5d5562f5SEiji Ota }
183*5d5562f5SEiji Ota 
184*5d5562f5SEiji Ota rdsv3_af_thr_t *
rdsv3_af_intr_thr_create(rdsv3_af_thr_drain_func_t fn,void * data,uint_t flag,rdsv3_af_grp_t * hcagp,ibt_cq_hdl_t ibt_cq_hdl)185*5d5562f5SEiji Ota rdsv3_af_intr_thr_create(rdsv3_af_thr_drain_func_t fn, void *data, uint_t flag,
186*5d5562f5SEiji Ota     rdsv3_af_grp_t *hcagp, ibt_cq_hdl_t ibt_cq_hdl)
187*5d5562f5SEiji Ota {
188*5d5562f5SEiji Ota 	rdsv3_af_thr_t *ringp;
189*5d5562f5SEiji Ota 	processorid_t cpuid;
190*5d5562f5SEiji Ota 
191*5d5562f5SEiji Ota 	if (ibt_cq_hdl == NULL)
192*5d5562f5SEiji Ota 		return (NULL);
193*5d5562f5SEiji Ota 	ringp = rdsv3_af_thr_create(fn, data, flag, hcagp);
194*5d5562f5SEiji Ota 	if (ringp == NULL)
195*5d5562f5SEiji Ota 		return (NULL);
196*5d5562f5SEiji Ota 
197*5d5562f5SEiji Ota 	mutex_enter(&cpu_lock);
198*5d5562f5SEiji Ota 	if (hcagp->g_conn_cpuid_idx >= RDSV3_AFT_CONN_CPU_POOL)
199*5d5562f5SEiji Ota 		hcagp->g_conn_cpuid_idx = 0;
200*5d5562f5SEiji Ota 	cpuid =  hcagp->g_conn_cpuid_pool[hcagp->g_conn_cpuid_idx++];
201*5d5562f5SEiji Ota 	(void) rdsv3_af_thr_bind(ringp, cpuid);
202*5d5562f5SEiji Ota 	mutex_exit(&cpu_lock);
203*5d5562f5SEiji Ota 
204*5d5562f5SEiji Ota 	if (ringp->aft_intr) {
205*5d5562f5SEiji Ota 		if (rdsv3_intr_line_up_mode) {
206*5d5562f5SEiji Ota 			(void) ddi_intr_set_affinity(ringp->aft_intr, cpuid);
207*5d5562f5SEiji Ota 		} else {
208*5d5562f5SEiji Ota 			(void) ddi_intr_set_affinity(ringp->aft_intr,
209*5d5562f5SEiji Ota 			    rdsv3_msix_pool[0]);
210*5d5562f5SEiji Ota 		}
211*5d5562f5SEiji Ota 	}
212*5d5562f5SEiji Ota 	return (ringp);
213*5d5562f5SEiji Ota }
214*5d5562f5SEiji Ota 
215*5d5562f5SEiji Ota rdsv3_af_thr_t *
rdsv3_af_thr_create(rdsv3_af_thr_drain_func_t fn,void * data,uint_t flag,rdsv3_af_grp_t * hcagp)216*5d5562f5SEiji Ota rdsv3_af_thr_create(rdsv3_af_thr_drain_func_t fn, void *data, uint_t flag,
217*5d5562f5SEiji Ota     rdsv3_af_grp_t *hcagp)
218*5d5562f5SEiji Ota {
219*5d5562f5SEiji Ota 	rdsv3_af_thr_t *ringp;
220*5d5562f5SEiji Ota 	pri_t pri;
221*5d5562f5SEiji Ota 	uint_t l_flags = flag;
222*5d5562f5SEiji Ota 	rdsv3_af_grp_t *l_hcagp = hcagp;
223*5d5562f5SEiji Ota 
224*5d5562f5SEiji Ota 	ringp = kmem_zalloc(sizeof (rdsv3_af_thr_t), KM_NOSLEEP);
225*5d5562f5SEiji Ota 	if (ringp == NULL)
226*5d5562f5SEiji Ota 		return (NULL);
227*5d5562f5SEiji Ota 
228*5d5562f5SEiji Ota 	ringp->aft_grp = hcagp;
229*5d5562f5SEiji Ota 	mutex_init(&ringp->aft_lock, NULL, MUTEX_DEFAULT, NULL);
230*5d5562f5SEiji Ota 	cv_init(&ringp->aft_async, NULL, CV_DEFAULT, NULL);
231*5d5562f5SEiji Ota 	if (flag & SCQ_WRK_BIND_CPU)
232*5d5562f5SEiji Ota 		pri = maxclsyspri;
233*5d5562f5SEiji Ota 	else
234*5d5562f5SEiji Ota 		pri = maxclsyspri;
235*5d5562f5SEiji Ota 	ringp->aft_worker = thread_create(NULL, 0,
236*5d5562f5SEiji Ota 	    rdsv3_af_thr_worker, ringp, 0, &p0, TS_RUN, pri);
237*5d5562f5SEiji Ota 	ringp->aft_data = data;
238*5d5562f5SEiji Ota 	ringp->aft_drain_func = (rdsv3_af_thr_drain_func_t)fn;
239*5d5562f5SEiji Ota 
240*5d5562f5SEiji Ota 	/* set the bind CPU to -1 to indicate no thread affinity set */
241*5d5562f5SEiji Ota 	ringp->aft_cpuid = -1;
242*5d5562f5SEiji Ota 	ringp->aft_state = 0;
243*5d5562f5SEiji Ota 	ringp->aft_cflag = flag;
244*5d5562f5SEiji Ota 
245*5d5562f5SEiji Ota 	if (flag & SCQ_BIND_CPU) {
246*5d5562f5SEiji Ota 		mutex_enter(&cpu_lock);
247*5d5562f5SEiji Ota 		if (flag & SCQ_HCA_BIND_CPU) {
248*5d5562f5SEiji Ota 			(void) rdsv3_af_thr_bind(ringp, hcagp->g_hca_cpuid);
249*5d5562f5SEiji Ota 		} else if (flag & SCQ_WRK_BIND_CPU) {
250*5d5562f5SEiji Ota 			(void) rdsv3_af_thr_bind(ringp, hcagp->g_hca_cpuid);
251*5d5562f5SEiji Ota 		}
252*5d5562f5SEiji Ota 		mutex_exit(&cpu_lock);
253*5d5562f5SEiji Ota 	}
254*5d5562f5SEiji Ota 
255*5d5562f5SEiji Ota 	RDSV3_DPRINTF2("rdsv3_af_thr_create", "af_thr %p ic %p", ringp, data);
256*5d5562f5SEiji Ota 	return (ringp);
257*5d5562f5SEiji Ota }
258*5d5562f5SEiji Ota 
259*5d5562f5SEiji Ota void
rdsv3_af_thr_destroy(rdsv3_af_thr_t * ringp)260*5d5562f5SEiji Ota rdsv3_af_thr_destroy(rdsv3_af_thr_t *ringp)
261*5d5562f5SEiji Ota {
262*5d5562f5SEiji Ota 	RDSV3_DPRINTF2("rdsv3_af_thr_destroy", "af_thr %p", ringp);
263*5d5562f5SEiji Ota 
264*5d5562f5SEiji Ota 	/* wait until the af_thr has gone to sleep */
265*5d5562f5SEiji Ota 	mutex_enter(&ringp->aft_lock);
266*5d5562f5SEiji Ota 	while (ringp->aft_state & AFT_PROC) {
267*5d5562f5SEiji Ota 		mutex_exit(&ringp->aft_lock);
268*5d5562f5SEiji Ota 		delay(drv_usectohz(1000));
269*5d5562f5SEiji Ota 		mutex_enter(&ringp->aft_lock);
270*5d5562f5SEiji Ota 	}
271*5d5562f5SEiji Ota 	ringp->aft_state |= AFT_CONDEMNED;
272*5d5562f5SEiji Ota 	if (!(ringp->aft_state & AFT_PROC)) {
273*5d5562f5SEiji Ota 		cv_signal(&ringp->aft_async);
274*5d5562f5SEiji Ota 	}
275*5d5562f5SEiji Ota 	mutex_exit(&ringp->aft_lock);
276*5d5562f5SEiji Ota }
277*5d5562f5SEiji Ota 
278*5d5562f5SEiji Ota void
rdsv3_af_thr_fire(rdsv3_af_thr_t * ringp)279*5d5562f5SEiji Ota rdsv3_af_thr_fire(rdsv3_af_thr_t *ringp)
280*5d5562f5SEiji Ota {
281*5d5562f5SEiji Ota 	mutex_enter(&ringp->aft_lock);
282*5d5562f5SEiji Ota 	ringp->aft_state |= AFT_ARMED;
283*5d5562f5SEiji Ota 	if (!(ringp->aft_state & AFT_PROC)) {
284*5d5562f5SEiji Ota 		cv_signal(&ringp->aft_async);
285*5d5562f5SEiji Ota 	}
286*5d5562f5SEiji Ota 	mutex_exit(&ringp->aft_lock);
287*5d5562f5SEiji Ota }
288*5d5562f5SEiji Ota 
289*5d5562f5SEiji Ota static void
rdsv3_af_thr_worker(rdsv3_af_thr_t * ringp)290*5d5562f5SEiji Ota rdsv3_af_thr_worker(rdsv3_af_thr_t *ringp)
291*5d5562f5SEiji Ota {
292*5d5562f5SEiji Ota 	kmutex_t *lock = &ringp->aft_lock;
293*5d5562f5SEiji Ota 	kcondvar_t *async = &ringp->aft_async;
294*5d5562f5SEiji Ota 	callb_cpr_t cprinfo;
295*5d5562f5SEiji Ota 
296*5d5562f5SEiji Ota 	RDSV3_DPRINTF4("rdsv3_af_thr_worker", "Enter af_thr %p", ringp);
297*5d5562f5SEiji Ota 
298*5d5562f5SEiji Ota 	CALLB_CPR_INIT(&cprinfo, lock, callb_generic_cpr, "rdsv3_af_thr");
299*5d5562f5SEiji Ota 	mutex_enter(lock);
300*5d5562f5SEiji Ota 	for (;;) {
301*5d5562f5SEiji Ota 		while (!(ringp->aft_state & (AFT_ARMED | AFT_CONDEMNED))) {
302*5d5562f5SEiji Ota 			CALLB_CPR_SAFE_BEGIN(&cprinfo);
303*5d5562f5SEiji Ota 			cv_wait(async, lock);
304*5d5562f5SEiji Ota 			CALLB_CPR_SAFE_END(&cprinfo, lock);
305*5d5562f5SEiji Ota 		}
306*5d5562f5SEiji Ota 		ringp->aft_state &= ~AFT_ARMED;
307*5d5562f5SEiji Ota 
308*5d5562f5SEiji Ota 		/*
309*5d5562f5SEiji Ota 		 * Either we have work to do, or we have been asked to
310*5d5562f5SEiji Ota 		 * shutdown
311*5d5562f5SEiji Ota 		 */
312*5d5562f5SEiji Ota 		if (ringp->aft_state & AFT_CONDEMNED)
313*5d5562f5SEiji Ota 			goto done;
314*5d5562f5SEiji Ota 		ASSERT(!(ringp->aft_state & AFT_PROC));
315*5d5562f5SEiji Ota 		ringp->aft_state |= AFT_PROC;
316*5d5562f5SEiji Ota 		mutex_exit(&ringp->aft_lock);
317*5d5562f5SEiji Ota 
318*5d5562f5SEiji Ota 		ringp->aft_drain_func(ringp->aft_data);
319*5d5562f5SEiji Ota 
320*5d5562f5SEiji Ota 		mutex_enter(&ringp->aft_lock);
321*5d5562f5SEiji Ota 		ringp->aft_state &= ~AFT_PROC;
322*5d5562f5SEiji Ota 	}
323*5d5562f5SEiji Ota done:
324*5d5562f5SEiji Ota 	CALLB_CPR_EXIT(&cprinfo);
325*5d5562f5SEiji Ota 	RDSV3_DPRINTF2("rdsv3_af_thr_worker", "Exit af_thr %p", ringp);
326*5d5562f5SEiji Ota 	cv_destroy(&ringp->aft_async);
327*5d5562f5SEiji Ota 	mutex_destroy(&ringp->aft_lock);
328*5d5562f5SEiji Ota 	kmem_free(ringp, sizeof (rdsv3_af_thr_t));
329*5d5562f5SEiji Ota 	thread_exit();
330*5d5562f5SEiji Ota }
331*5d5562f5SEiji Ota 
332*5d5562f5SEiji Ota 
333*5d5562f5SEiji Ota int rdsv3_af_thr_thread_bind = 1;
334*5d5562f5SEiji Ota 
335*5d5562f5SEiji Ota /*
336*5d5562f5SEiji Ota  * Bind a soft ring worker thread to supplied CPU.
337*5d5562f5SEiji Ota  */
338*5d5562f5SEiji Ota cpu_t *
rdsv3_af_thr_bind(rdsv3_af_thr_t * ringp,processorid_t cpuid)339*5d5562f5SEiji Ota rdsv3_af_thr_bind(rdsv3_af_thr_t *ringp, processorid_t cpuid)
340*5d5562f5SEiji Ota {
341*5d5562f5SEiji Ota 	cpu_t *cp;
342*5d5562f5SEiji Ota 	boolean_t clear = B_FALSE;
343*5d5562f5SEiji Ota 
344*5d5562f5SEiji Ota 	ASSERT(MUTEX_HELD(&cpu_lock));
345*5d5562f5SEiji Ota 
346*5d5562f5SEiji Ota 	if (rdsv3_af_thr_thread_bind == 0) {
347*5d5562f5SEiji Ota 		return (NULL);
348*5d5562f5SEiji Ota 	}
349*5d5562f5SEiji Ota 
350*5d5562f5SEiji Ota 	cp = cpu_get(cpuid);
351*5d5562f5SEiji Ota 	if (cp == NULL || !cpu_is_online(cp))
352*5d5562f5SEiji Ota 		return (NULL);
353*5d5562f5SEiji Ota 
354*5d5562f5SEiji Ota 	mutex_enter(&ringp->aft_lock);
355*5d5562f5SEiji Ota 	ringp->aft_state |= AFT_BOUND;
356*5d5562f5SEiji Ota 	if (ringp->aft_cpuid != -1)
357*5d5562f5SEiji Ota 		clear = B_TRUE;
358*5d5562f5SEiji Ota 	ringp->aft_cpuid = cpuid;
359*5d5562f5SEiji Ota 	mutex_exit(&ringp->aft_lock);
360*5d5562f5SEiji Ota 
361*5d5562f5SEiji Ota 	if (clear)
362*5d5562f5SEiji Ota 		thread_affinity_clear(ringp->aft_worker);
363*5d5562f5SEiji Ota 
364*5d5562f5SEiji Ota 	RDSV3_DPRINTF4("rdsv3_af_thr_bind", "Bound af_thr %p to cpu %d",
365*5d5562f5SEiji Ota 	    ringp, cpuid);
366*5d5562f5SEiji Ota 	thread_affinity_set(ringp->aft_worker, cpuid);
367*5d5562f5SEiji Ota 	return (cp);
368*5d5562f5SEiji Ota }
369*5d5562f5SEiji Ota 
370*5d5562f5SEiji Ota /*
371*5d5562f5SEiji Ota  * Un Bind a soft ring worker thread.
372*5d5562f5SEiji Ota  */
373*5d5562f5SEiji Ota static void
rdsv3_af_thr_unbind(rdsv3_af_thr_t * ringp)374*5d5562f5SEiji Ota rdsv3_af_thr_unbind(rdsv3_af_thr_t *ringp)
375*5d5562f5SEiji Ota {
376*5d5562f5SEiji Ota 	ASSERT(MUTEX_HELD(&cpu_lock));
377*5d5562f5SEiji Ota 
378*5d5562f5SEiji Ota 	mutex_enter(&ringp->aft_lock);
379*5d5562f5SEiji Ota 	if (!(ringp->aft_state & AFT_BOUND)) {
380*5d5562f5SEiji Ota 		ASSERT(ringp->aft_cpuid == -1);
381*5d5562f5SEiji Ota 		mutex_exit(&ringp->aft_lock);
382*5d5562f5SEiji Ota 		return;
383*5d5562f5SEiji Ota 	}
384*5d5562f5SEiji Ota 
385*5d5562f5SEiji Ota 	ringp->aft_cpuid = -1;
386*5d5562f5SEiji Ota 	ringp->aft_state &= ~AFT_BOUND;
387*5d5562f5SEiji Ota 	thread_affinity_clear(ringp->aft_worker);
388*5d5562f5SEiji Ota 	mutex_exit(&ringp->aft_lock);
389*5d5562f5SEiji Ota }
390