xref: /freebsd/sys/dev/ocs_fc/ocs_domain.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1*ef270ab1SKenneth D. Merry /*-
2*ef270ab1SKenneth D. Merry  * Copyright (c) 2017 Broadcom. All rights reserved.
3*ef270ab1SKenneth D. Merry  * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
4*ef270ab1SKenneth D. Merry  *
5*ef270ab1SKenneth D. Merry  * Redistribution and use in source and binary forms, with or without
6*ef270ab1SKenneth D. Merry  * modification, are permitted provided that the following conditions are met:
7*ef270ab1SKenneth D. Merry  *
8*ef270ab1SKenneth D. Merry  * 1. Redistributions of source code must retain the above copyright notice,
9*ef270ab1SKenneth D. Merry  *    this list of conditions and the following disclaimer.
10*ef270ab1SKenneth D. Merry  *
11*ef270ab1SKenneth D. Merry  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*ef270ab1SKenneth D. Merry  *    this list of conditions and the following disclaimer in the documentation
13*ef270ab1SKenneth D. Merry  *    and/or other materials provided with the distribution.
14*ef270ab1SKenneth D. Merry  *
15*ef270ab1SKenneth D. Merry  * 3. Neither the name of the copyright holder nor the names of its contributors
16*ef270ab1SKenneth D. Merry  *    may be used to endorse or promote products derived from this software
17*ef270ab1SKenneth D. Merry  *    without specific prior written permission.
18*ef270ab1SKenneth D. Merry  *
19*ef270ab1SKenneth D. Merry  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20*ef270ab1SKenneth D. Merry  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*ef270ab1SKenneth D. Merry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*ef270ab1SKenneth D. Merry  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23*ef270ab1SKenneth D. Merry  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*ef270ab1SKenneth D. Merry  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*ef270ab1SKenneth D. Merry  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*ef270ab1SKenneth D. Merry  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*ef270ab1SKenneth D. Merry  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*ef270ab1SKenneth D. Merry  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*ef270ab1SKenneth D. Merry  * POSSIBILITY OF SUCH DAMAGE.
30*ef270ab1SKenneth D. Merry  */
31*ef270ab1SKenneth D. Merry 
32*ef270ab1SKenneth D. Merry /**
33*ef270ab1SKenneth D. Merry  * @file
34*ef270ab1SKenneth D. Merry  * Handles the domain object callback from the HW.
35*ef270ab1SKenneth D. Merry  */
36*ef270ab1SKenneth D. Merry 
37*ef270ab1SKenneth D. Merry /*!
38*ef270ab1SKenneth D. Merry @defgroup domain_sm Domain State Machine: States
39*ef270ab1SKenneth D. Merry */
40*ef270ab1SKenneth D. Merry 
41*ef270ab1SKenneth D. Merry #include "ocs.h"
42*ef270ab1SKenneth D. Merry 
43*ef270ab1SKenneth D. Merry #include "ocs_fabric.h"
44*ef270ab1SKenneth D. Merry #include "ocs_device.h"
45*ef270ab1SKenneth D. Merry 
46*ef270ab1SKenneth D. Merry #define domain_sm_trace(domain)  \
47*ef270ab1SKenneth D. Merry 	do { \
48*ef270ab1SKenneth D. Merry 		if (OCS_LOG_ENABLE_DOMAIN_SM_TRACE(domain->ocs)) \
49*ef270ab1SKenneth D. Merry 			ocs_log_info(domain->ocs, "[domain] %-20s %-20s\n", __func__, ocs_sm_event_name(evt)); \
50*ef270ab1SKenneth D. Merry 	} while (0)
51*ef270ab1SKenneth D. Merry 
52*ef270ab1SKenneth D. Merry #define domain_trace(domain, fmt, ...) \
53*ef270ab1SKenneth D. Merry 	do { \
54*ef270ab1SKenneth D. Merry 		if (OCS_LOG_ENABLE_DOMAIN_SM_TRACE(domain ? domain->ocs : NULL)) \
55*ef270ab1SKenneth D. Merry 			ocs_log_info(domain ? domain->ocs : NULL, fmt, ##__VA_ARGS__); \
56*ef270ab1SKenneth D. Merry 	} while (0)
57*ef270ab1SKenneth D. Merry 
58*ef270ab1SKenneth D. Merry #define domain_printf(domain, fmt, ...) \
59*ef270ab1SKenneth D. Merry 	do { \
60*ef270ab1SKenneth D. Merry 		ocs_log_info(domain ? domain->ocs : NULL, fmt, ##__VA_ARGS__); \
61*ef270ab1SKenneth D. Merry 	} while (0)
62*ef270ab1SKenneth D. Merry 
63*ef270ab1SKenneth D. Merry void ocs_mgmt_domain_list(ocs_textbuf_t *textbuf, void *domain);
64*ef270ab1SKenneth D. Merry void ocs_mgmt_domain_get_all(ocs_textbuf_t *textbuf, void *domain);
65*ef270ab1SKenneth D. Merry int ocs_mgmt_domain_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *domain);
66*ef270ab1SKenneth D. Merry int ocs_mgmt_domain_set(char *parent, char *name, char *value, void *domain);
67*ef270ab1SKenneth D. Merry int ocs_mgmt_domain_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
68*ef270ab1SKenneth D. Merry 		void *arg_out, uint32_t arg_out_length, void *domain);
69*ef270ab1SKenneth D. Merry 
70*ef270ab1SKenneth D. Merry static ocs_mgmt_functions_t domain_mgmt_functions = {
71*ef270ab1SKenneth D. Merry 	.get_list_handler = ocs_mgmt_domain_list,
72*ef270ab1SKenneth D. Merry 	.get_handler = ocs_mgmt_domain_get,
73*ef270ab1SKenneth D. Merry 	.get_all_handler = ocs_mgmt_domain_get_all,
74*ef270ab1SKenneth D. Merry 	.set_handler = ocs_mgmt_domain_set,
75*ef270ab1SKenneth D. Merry 	.exec_handler = ocs_mgmt_domain_exec,
76*ef270ab1SKenneth D. Merry };
77*ef270ab1SKenneth D. Merry 
78*ef270ab1SKenneth D. Merry /**
79*ef270ab1SKenneth D. Merry  * @brief Accept domain callback events from the HW.
80*ef270ab1SKenneth D. Merry  *
81*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
82*ef270ab1SKenneth D. Merry  * HW calls this function with various domain-related events.
83*ef270ab1SKenneth D. Merry  *
84*ef270ab1SKenneth D. Merry  * @param arg Application-specified argument.
85*ef270ab1SKenneth D. Merry  * @param event Domain event.
86*ef270ab1SKenneth D. Merry  * @param data Event specific data.
87*ef270ab1SKenneth D. Merry  *
88*ef270ab1SKenneth D. Merry  * @return Returns 0 on success; or a negative error value on failure.
89*ef270ab1SKenneth D. Merry  */
90*ef270ab1SKenneth D. Merry 
91*ef270ab1SKenneth D. Merry int32_t
ocs_domain_cb(void * arg,ocs_hw_domain_event_e event,void * data)92*ef270ab1SKenneth D. Merry ocs_domain_cb(void *arg, ocs_hw_domain_event_e event, void *data)
93*ef270ab1SKenneth D. Merry {
94*ef270ab1SKenneth D. Merry 	ocs_t *ocs = arg;
95*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = NULL;
96*ef270ab1SKenneth D. Merry 	int32_t rc = 0;
97*ef270ab1SKenneth D. Merry 
98*ef270ab1SKenneth D. Merry 	ocs_assert(data, -1);
99*ef270ab1SKenneth D. Merry 
100*ef270ab1SKenneth D. Merry 	if (event != OCS_HW_DOMAIN_FOUND) {
101*ef270ab1SKenneth D. Merry 		domain = data;
102*ef270ab1SKenneth D. Merry 	}
103*ef270ab1SKenneth D. Merry 
104*ef270ab1SKenneth D. Merry 	switch (event) {
105*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_FOUND: {
106*ef270ab1SKenneth D. Merry 		uint64_t fcf_wwn = 0;
107*ef270ab1SKenneth D. Merry 		ocs_domain_record_t *drec = data;
108*ef270ab1SKenneth D. Merry 		ocs_assert(drec, -1);
109*ef270ab1SKenneth D. Merry 
110*ef270ab1SKenneth D. Merry 		/* extract the fcf_wwn */
111*ef270ab1SKenneth D. Merry 		fcf_wwn = ocs_be64toh(*((uint64_t*)drec->wwn));
112*ef270ab1SKenneth D. Merry 
113*ef270ab1SKenneth D. Merry 		/* lookup domain, or allocate a new one if one doesn't exist already */
114*ef270ab1SKenneth D. Merry 		domain = ocs_domain_find(ocs, fcf_wwn);
115*ef270ab1SKenneth D. Merry 		if (domain == NULL) {
116*ef270ab1SKenneth D. Merry 			domain = ocs_domain_alloc(ocs, fcf_wwn);
117*ef270ab1SKenneth D. Merry 			if (domain == NULL) {
118*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "ocs_domain_alloc() failed\n");
119*ef270ab1SKenneth D. Merry 				rc = -1;
120*ef270ab1SKenneth D. Merry 				break;
121*ef270ab1SKenneth D. Merry 			}
122*ef270ab1SKenneth D. Merry 			ocs_sm_transition(&domain->drvsm, __ocs_domain_init, NULL);
123*ef270ab1SKenneth D. Merry 		}
124*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_FOUND, drec);
125*ef270ab1SKenneth D. Merry 		break;
126*ef270ab1SKenneth D. Merry 	}
127*ef270ab1SKenneth D. Merry 
128*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_LOST:
129*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_LOST:\n");
130*ef270ab1SKenneth D. Merry 		ocs_domain_hold_frames(domain);
131*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_LOST, NULL);
132*ef270ab1SKenneth D. Merry 		break;
133*ef270ab1SKenneth D. Merry 
134*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_ALLOC_OK: {
135*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_ALLOC_OK:\n");
136*ef270ab1SKenneth D. Merry 		domain->instance_index = 0;
137*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_ALLOC_OK, NULL);
138*ef270ab1SKenneth D. Merry 		break;
139*ef270ab1SKenneth D. Merry 	}
140*ef270ab1SKenneth D. Merry 
141*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_ALLOC_FAIL:
142*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_ALLOC_FAIL:\n");
143*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_ALLOC_FAIL, NULL);
144*ef270ab1SKenneth D. Merry 		break;
145*ef270ab1SKenneth D. Merry 
146*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_ATTACH_OK:
147*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_ATTACH_OK:\n");
148*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_ATTACH_OK, NULL);
149*ef270ab1SKenneth D. Merry 		break;
150*ef270ab1SKenneth D. Merry 
151*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_ATTACH_FAIL:
152*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_ATTACH_FAIL:\n");
153*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_ATTACH_FAIL, NULL);
154*ef270ab1SKenneth D. Merry 		break;
155*ef270ab1SKenneth D. Merry 
156*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_FREE_OK:
157*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_FREE_OK:\n");
158*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_FREE_OK, NULL);
159*ef270ab1SKenneth D. Merry 		break;
160*ef270ab1SKenneth D. Merry 
161*ef270ab1SKenneth D. Merry 	case OCS_HW_DOMAIN_FREE_FAIL:
162*ef270ab1SKenneth D. Merry 		domain_trace(domain, "OCS_HW_DOMAIN_FREE_FAIL:\n");
163*ef270ab1SKenneth D. Merry 		ocs_domain_post_event(domain, OCS_EVT_DOMAIN_FREE_FAIL, NULL);
164*ef270ab1SKenneth D. Merry 		break;
165*ef270ab1SKenneth D. Merry 
166*ef270ab1SKenneth D. Merry 	default:
167*ef270ab1SKenneth D. Merry 		ocs_log_warn(ocs, "unsupported event %#x\n", event);
168*ef270ab1SKenneth D. Merry 	}
169*ef270ab1SKenneth D. Merry 
170*ef270ab1SKenneth D. Merry 	return rc;
171*ef270ab1SKenneth D. Merry }
172*ef270ab1SKenneth D. Merry 
173*ef270ab1SKenneth D. Merry /**
174*ef270ab1SKenneth D. Merry  * @brief Find the domain, given its FCF_WWN.
175*ef270ab1SKenneth D. Merry  *
176*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
177*ef270ab1SKenneth D. Merry  * Search the domain_list to find a matching domain object.
178*ef270ab1SKenneth D. Merry  *
179*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the OCS device.
180*ef270ab1SKenneth D. Merry  * @param fcf_wwn FCF WWN to find.
181*ef270ab1SKenneth D. Merry  *
182*ef270ab1SKenneth D. Merry  * @return Returns the pointer to the domain if found; or NULL otherwise.
183*ef270ab1SKenneth D. Merry  */
184*ef270ab1SKenneth D. Merry 
185*ef270ab1SKenneth D. Merry ocs_domain_t *
ocs_domain_find(ocs_t * ocs,uint64_t fcf_wwn)186*ef270ab1SKenneth D. Merry ocs_domain_find(ocs_t *ocs, uint64_t fcf_wwn)
187*ef270ab1SKenneth D. Merry {
188*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = NULL;
189*ef270ab1SKenneth D. Merry 
190*ef270ab1SKenneth D. Merry 	/* Check to see if this domain is already allocated */
191*ef270ab1SKenneth D. Merry 	ocs_device_lock(ocs);
192*ef270ab1SKenneth D. Merry 		ocs_list_foreach(&ocs->domain_list, domain) {
193*ef270ab1SKenneth D. Merry 			if (fcf_wwn == domain->fcf_wwn) {
194*ef270ab1SKenneth D. Merry 				break;
195*ef270ab1SKenneth D. Merry 			}
196*ef270ab1SKenneth D. Merry 		}
197*ef270ab1SKenneth D. Merry 	ocs_device_unlock(ocs);
198*ef270ab1SKenneth D. Merry 	return domain;
199*ef270ab1SKenneth D. Merry }
200*ef270ab1SKenneth D. Merry 
201*ef270ab1SKenneth D. Merry /**
202*ef270ab1SKenneth D. Merry  * @brief Allocate a domain object.
203*ef270ab1SKenneth D. Merry  *
204*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
205*ef270ab1SKenneth D. Merry  * A domain object is allocated and initialized. It is associated with the
206*ef270ab1SKenneth D. Merry  * \c ocs argument.
207*ef270ab1SKenneth D. Merry  *
208*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the OCS device.
209*ef270ab1SKenneth D. Merry  * @param fcf_wwn FCF WWN of the domain.
210*ef270ab1SKenneth D. Merry  *
211*ef270ab1SKenneth D. Merry  * @return Returns a pointer to the ocs_domain_t object; or NULL.
212*ef270ab1SKenneth D. Merry  */
213*ef270ab1SKenneth D. Merry 
214*ef270ab1SKenneth D. Merry ocs_domain_t *
ocs_domain_alloc(ocs_t * ocs,uint64_t fcf_wwn)215*ef270ab1SKenneth D. Merry ocs_domain_alloc(ocs_t *ocs, uint64_t fcf_wwn)
216*ef270ab1SKenneth D. Merry {
217*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain;
218*ef270ab1SKenneth D. Merry 
219*ef270ab1SKenneth D. Merry 	ocs_assert(ocs, NULL);
220*ef270ab1SKenneth D. Merry 
221*ef270ab1SKenneth D. Merry 	domain = ocs_malloc(ocs, sizeof(*domain), OCS_M_NOWAIT | OCS_M_ZERO);
222*ef270ab1SKenneth D. Merry 	if (domain) {
223*ef270ab1SKenneth D. Merry 		domain->ocs = ocs;
224*ef270ab1SKenneth D. Merry 		domain->instance_index = ocs->domain_instance_count++;
225*ef270ab1SKenneth D. Merry 		domain->drvsm.app = domain;
226*ef270ab1SKenneth D. Merry 		ocs_domain_lock_init(domain);
227*ef270ab1SKenneth D. Merry 		ocs_lock_init(ocs, &domain->lookup_lock, "Domain lookup[%d]", domain->instance_index);
228*ef270ab1SKenneth D. Merry 
229*ef270ab1SKenneth D. Merry 		/* Allocate a sparse vector for sport FC_ID's */
230*ef270ab1SKenneth D. Merry 		domain->lookup = spv_new(ocs);
231*ef270ab1SKenneth D. Merry 		if (domain->lookup == NULL) {
232*ef270ab1SKenneth D. Merry 			ocs_log_err(ocs, "spv_new() failed\n");
233*ef270ab1SKenneth D. Merry 			ocs_free(ocs, domain, sizeof(*domain));
234*ef270ab1SKenneth D. Merry 			return NULL;
235*ef270ab1SKenneth D. Merry 		}
236*ef270ab1SKenneth D. Merry 
237*ef270ab1SKenneth D. Merry 		ocs_list_init(&domain->sport_list, ocs_sport_t, link);
238*ef270ab1SKenneth D. Merry 		domain->fcf_wwn = fcf_wwn;
239*ef270ab1SKenneth D. Merry 		ocs_log_debug(ocs, "Domain allocated: wwn %016" PRIX64 "\n", domain->fcf_wwn);
240*ef270ab1SKenneth D. Merry 		domain->femul_enable = (ocs->ctrlmask & OCS_CTRLMASK_ENABLE_FABRIC_EMULATION) != 0;
241*ef270ab1SKenneth D. Merry 
242*ef270ab1SKenneth D. Merry 		ocs_device_lock(ocs);
243*ef270ab1SKenneth D. Merry 			/* if this is the first domain, then assign it as the "root" domain */
244*ef270ab1SKenneth D. Merry 			if (ocs_list_empty(&ocs->domain_list)) {
245*ef270ab1SKenneth D. Merry 				ocs->domain = domain;
246*ef270ab1SKenneth D. Merry 			}
247*ef270ab1SKenneth D. Merry 			ocs_list_add_tail(&ocs->domain_list, domain);
248*ef270ab1SKenneth D. Merry 		ocs_device_unlock(ocs);
249*ef270ab1SKenneth D. Merry 
250*ef270ab1SKenneth D. Merry 		domain->mgmt_functions = &domain_mgmt_functions;
251*ef270ab1SKenneth D. Merry 	} else {
252*ef270ab1SKenneth D. Merry 		ocs_log_err(ocs, "domain allocation failed\n");
253*ef270ab1SKenneth D. Merry 	}
254*ef270ab1SKenneth D. Merry 
255*ef270ab1SKenneth D. Merry 	return domain;
256*ef270ab1SKenneth D. Merry }
257*ef270ab1SKenneth D. Merry 
258*ef270ab1SKenneth D. Merry /**
259*ef270ab1SKenneth D. Merry  * @brief Free a domain object.
260*ef270ab1SKenneth D. Merry  *
261*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
262*ef270ab1SKenneth D. Merry  * The domain object is freed.
263*ef270ab1SKenneth D. Merry  *
264*ef270ab1SKenneth D. Merry  * @param domain Domain object to free.
265*ef270ab1SKenneth D. Merry  *
266*ef270ab1SKenneth D. Merry  * @return None.
267*ef270ab1SKenneth D. Merry  */
268*ef270ab1SKenneth D. Merry 
269*ef270ab1SKenneth D. Merry void
ocs_domain_free(ocs_domain_t * domain)270*ef270ab1SKenneth D. Merry ocs_domain_free(ocs_domain_t *domain)
271*ef270ab1SKenneth D. Merry {
272*ef270ab1SKenneth D. Merry 	ocs_t *ocs;
273*ef270ab1SKenneth D. Merry 
274*ef270ab1SKenneth D. Merry 	ocs_assert(domain);
275*ef270ab1SKenneth D. Merry 	ocs_assert(domain->ocs);
276*ef270ab1SKenneth D. Merry 
277*ef270ab1SKenneth D. Merry 	/* Hold frames to clear the domain pointer from the xport lookup */
278*ef270ab1SKenneth D. Merry 	ocs_domain_hold_frames(domain);
279*ef270ab1SKenneth D. Merry 
280*ef270ab1SKenneth D. Merry 	ocs = domain->ocs;
281*ef270ab1SKenneth D. Merry 
282*ef270ab1SKenneth D. Merry 	ocs_log_debug(ocs, "Domain free: wwn %016" PRIX64 "\n", domain->fcf_wwn);
283*ef270ab1SKenneth D. Merry 
284*ef270ab1SKenneth D. Merry 	spv_del(domain->lookup);
285*ef270ab1SKenneth D. Merry 	domain->lookup = NULL;
286*ef270ab1SKenneth D. Merry 
287*ef270ab1SKenneth D. Merry 	ocs_device_lock(ocs);
288*ef270ab1SKenneth D. Merry 		ocs_list_remove(&ocs->domain_list, domain);
289*ef270ab1SKenneth D. Merry 		if (domain == ocs->domain) {
290*ef270ab1SKenneth D. Merry 			/* set global domain to the new head */
291*ef270ab1SKenneth D. Merry 			ocs->domain = ocs_list_get_head(&ocs->domain_list);
292*ef270ab1SKenneth D. Merry 			if (ocs->domain) {
293*ef270ab1SKenneth D. Merry 				ocs_log_debug(ocs, "setting new domain, old=%p new=%p\n",
294*ef270ab1SKenneth D. Merry 						domain, ocs->domain);
295*ef270ab1SKenneth D. Merry 			}
296*ef270ab1SKenneth D. Merry 		}
297*ef270ab1SKenneth D. Merry 
298*ef270ab1SKenneth D. Merry 		if (ocs_list_empty(&ocs->domain_list) && ocs->domain_list_empty_cb ) {
299*ef270ab1SKenneth D. Merry 			(*ocs->domain_list_empty_cb)(ocs, ocs->domain_list_empty_cb_arg);
300*ef270ab1SKenneth D. Merry 		}
301*ef270ab1SKenneth D. Merry 	ocs_device_unlock(ocs);
302*ef270ab1SKenneth D. Merry 
303*ef270ab1SKenneth D. Merry 	ocs_lock_free(&domain->lookup_lock);
304*ef270ab1SKenneth D. Merry 
305*ef270ab1SKenneth D. Merry 	ocs_free(ocs, domain, sizeof(*domain));
306*ef270ab1SKenneth D. Merry }
307*ef270ab1SKenneth D. Merry 
308*ef270ab1SKenneth D. Merry /**
309*ef270ab1SKenneth D. Merry  * @brief Free memory resources of a domain object.
310*ef270ab1SKenneth D. Merry  *
311*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
312*ef270ab1SKenneth D. Merry  * After the domain object is freed, its child objects are also freed.
313*ef270ab1SKenneth D. Merry  *
314*ef270ab1SKenneth D. Merry  * @param domain Pointer to a domain object.
315*ef270ab1SKenneth D. Merry  *
316*ef270ab1SKenneth D. Merry  * @return None.
317*ef270ab1SKenneth D. Merry  */
318*ef270ab1SKenneth D. Merry 
319*ef270ab1SKenneth D. Merry void
ocs_domain_force_free(ocs_domain_t * domain)320*ef270ab1SKenneth D. Merry ocs_domain_force_free(ocs_domain_t *domain)
321*ef270ab1SKenneth D. Merry {
322*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
323*ef270ab1SKenneth D. Merry 	ocs_sport_t *next;
324*ef270ab1SKenneth D. Merry 
325*ef270ab1SKenneth D. Merry 	/* Shutdown domain sm */
326*ef270ab1SKenneth D. Merry 	ocs_sm_disable(&domain->drvsm);
327*ef270ab1SKenneth D. Merry 
328*ef270ab1SKenneth D. Merry 	ocs_scsi_notify_domain_force_free(domain);
329*ef270ab1SKenneth D. Merry 
330*ef270ab1SKenneth D. Merry 	ocs_domain_lock(domain);
331*ef270ab1SKenneth D. Merry 		ocs_list_foreach_safe(&domain->sport_list, sport, next) {
332*ef270ab1SKenneth D. Merry 			ocs_sport_force_free(sport);
333*ef270ab1SKenneth D. Merry 		}
334*ef270ab1SKenneth D. Merry 	ocs_domain_unlock(domain);
335*ef270ab1SKenneth D. Merry 	ocs_hw_domain_force_free(&domain->ocs->hw, domain);
336*ef270ab1SKenneth D. Merry 	ocs_domain_free(domain);
337*ef270ab1SKenneth D. Merry }
338*ef270ab1SKenneth D. Merry 
339*ef270ab1SKenneth D. Merry /**
340*ef270ab1SKenneth D. Merry  * @brief Register a callback when the domain_list goes empty.
341*ef270ab1SKenneth D. Merry  *
342*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
343*ef270ab1SKenneth D. Merry  * A function callback may be registered when the domain_list goes empty.
344*ef270ab1SKenneth D. Merry  *
345*ef270ab1SKenneth D. Merry  * @param ocs Pointer to a device object.
346*ef270ab1SKenneth D. Merry  * @param callback Callback function.
347*ef270ab1SKenneth D. Merry  * @param arg Callback argument.
348*ef270ab1SKenneth D. Merry  *
349*ef270ab1SKenneth D. Merry  * @return None.
350*ef270ab1SKenneth D. Merry  */
351*ef270ab1SKenneth D. Merry 
352*ef270ab1SKenneth D. Merry void
ocs_register_domain_list_empty_cb(ocs_t * ocs,void (* callback)(ocs_t * ocs,void * arg),void * arg)353*ef270ab1SKenneth D. Merry ocs_register_domain_list_empty_cb(ocs_t *ocs, void (*callback)(ocs_t *ocs, void *arg), void *arg)
354*ef270ab1SKenneth D. Merry {
355*ef270ab1SKenneth D. Merry 	ocs_device_lock(ocs);
356*ef270ab1SKenneth D. Merry 		ocs->domain_list_empty_cb = callback;
357*ef270ab1SKenneth D. Merry 		ocs->domain_list_empty_cb_arg = arg;
358*ef270ab1SKenneth D. Merry 		if (ocs_list_empty(&ocs->domain_list) && callback) {
359*ef270ab1SKenneth D. Merry 			(*callback)(ocs, arg);
360*ef270ab1SKenneth D. Merry 		}
361*ef270ab1SKenneth D. Merry 	ocs_device_unlock(ocs);
362*ef270ab1SKenneth D. Merry }
363*ef270ab1SKenneth D. Merry 
364*ef270ab1SKenneth D. Merry /**
365*ef270ab1SKenneth D. Merry  * @brief Return a pointer to the domain, given the instance index.
366*ef270ab1SKenneth D. Merry  *
367*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
368*ef270ab1SKenneth D. Merry  * A pointer to the domain context, given by the index, is returned.
369*ef270ab1SKenneth D. Merry  *
370*ef270ab1SKenneth D. Merry  * @param ocs Pointer to the driver instance context.
371*ef270ab1SKenneth D. Merry  * @param index Instance index.
372*ef270ab1SKenneth D. Merry  *
373*ef270ab1SKenneth D. Merry  * @return Returns a pointer to the domain; or NULL.
374*ef270ab1SKenneth D. Merry  */
375*ef270ab1SKenneth D. Merry 
376*ef270ab1SKenneth D. Merry ocs_domain_t *
ocs_domain_get_instance(ocs_t * ocs,uint32_t index)377*ef270ab1SKenneth D. Merry ocs_domain_get_instance(ocs_t *ocs, uint32_t index)
378*ef270ab1SKenneth D. Merry {
379*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = NULL;
380*ef270ab1SKenneth D. Merry 
381*ef270ab1SKenneth D. Merry 	if (index >= OCS_MAX_DOMAINS) {
382*ef270ab1SKenneth D. Merry 		ocs_log_err(ocs, "invalid index: %d\n", index);
383*ef270ab1SKenneth D. Merry 		return NULL;
384*ef270ab1SKenneth D. Merry 	}
385*ef270ab1SKenneth D. Merry 	ocs_device_lock(ocs);
386*ef270ab1SKenneth D. Merry 		ocs_list_foreach(&ocs->domain_list, domain) {
387*ef270ab1SKenneth D. Merry 			if (domain->instance_index == index) {
388*ef270ab1SKenneth D. Merry 				break;
389*ef270ab1SKenneth D. Merry 			}
390*ef270ab1SKenneth D. Merry 		}
391*ef270ab1SKenneth D. Merry 	ocs_device_unlock(ocs);
392*ef270ab1SKenneth D. Merry 	return domain;
393*ef270ab1SKenneth D. Merry }
394*ef270ab1SKenneth D. Merry 
395*ef270ab1SKenneth D. Merry /**
396*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
397*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Common event handler.
398*ef270ab1SKenneth D. Merry  *
399*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
400*ef270ab1SKenneth D. Merry  * Common/shared events are handled here for the domain state machine.
401*ef270ab1SKenneth D. Merry  *
402*ef270ab1SKenneth D. Merry  * @param funcname Function name text.
403*ef270ab1SKenneth D. Merry  * @param ctx Domain state machine context.
404*ef270ab1SKenneth D. Merry  * @param evt Event to process.
405*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
406*ef270ab1SKenneth D. Merry  *
407*ef270ab1SKenneth D. Merry  * @return Returns NULL.
408*ef270ab1SKenneth D. Merry  */
409*ef270ab1SKenneth D. Merry 
410*ef270ab1SKenneth D. Merry static void *
__ocs_domain_common(const char * funcname,ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)411*ef270ab1SKenneth D. Merry __ocs_domain_common(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
412*ef270ab1SKenneth D. Merry {
413*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = ctx->app;
414*ef270ab1SKenneth D. Merry 
415*ef270ab1SKenneth D. Merry 	switch(evt) {
416*ef270ab1SKenneth D. Merry 	case OCS_EVT_ENTER:
417*ef270ab1SKenneth D. Merry 	case OCS_EVT_REENTER:
418*ef270ab1SKenneth D. Merry 	case OCS_EVT_EXIT:
419*ef270ab1SKenneth D. Merry 	case OCS_EVT_ALL_CHILD_NODES_FREE:
420*ef270ab1SKenneth D. Merry 		/* this can arise if an FLOGI fails on the SPORT, and the SPORT is shutdown */
421*ef270ab1SKenneth D. Merry 		break;
422*ef270ab1SKenneth D. Merry 	default:
423*ef270ab1SKenneth D. Merry 		ocs_log_warn(domain->ocs, "%-20s %-20s not handled\n", funcname, ocs_sm_event_name(evt));
424*ef270ab1SKenneth D. Merry 		break;
425*ef270ab1SKenneth D. Merry 	}
426*ef270ab1SKenneth D. Merry 
427*ef270ab1SKenneth D. Merry 	return NULL;
428*ef270ab1SKenneth D. Merry }
429*ef270ab1SKenneth D. Merry 
430*ef270ab1SKenneth D. Merry /**
431*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
432*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Common shutdown.
433*ef270ab1SKenneth D. Merry  *
434*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
435*ef270ab1SKenneth D. Merry  * Handles common shutdown events.
436*ef270ab1SKenneth D. Merry  *
437*ef270ab1SKenneth D. Merry  * @param funcname Function name text.
438*ef270ab1SKenneth D. Merry  * @param ctx Remote node state machine context.
439*ef270ab1SKenneth D. Merry  * @param evt Event to process.
440*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
441*ef270ab1SKenneth D. Merry  *
442*ef270ab1SKenneth D. Merry  * @return Returns NULL.
443*ef270ab1SKenneth D. Merry  */
444*ef270ab1SKenneth D. Merry 
445*ef270ab1SKenneth D. Merry static void *
__ocs_domain_common_shutdown(const char * funcname,ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)446*ef270ab1SKenneth D. Merry __ocs_domain_common_shutdown(const char *funcname, ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
447*ef270ab1SKenneth D. Merry {
448*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = ctx->app;
449*ef270ab1SKenneth D. Merry 
450*ef270ab1SKenneth D. Merry 	switch(evt) {
451*ef270ab1SKenneth D. Merry 	case OCS_EVT_ENTER:
452*ef270ab1SKenneth D. Merry 	case OCS_EVT_REENTER:
453*ef270ab1SKenneth D. Merry 	case OCS_EVT_EXIT:
454*ef270ab1SKenneth D. Merry 		break;
455*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FOUND:
456*ef270ab1SKenneth D. Merry 		ocs_assert(arg, NULL);
457*ef270ab1SKenneth D. Merry 		/* sm: / save drec, mark domain_found_pending */
458*ef270ab1SKenneth D. Merry 		ocs_memcpy(&domain->pending_drec, arg, sizeof(domain->pending_drec));
459*ef270ab1SKenneth D. Merry 		domain->domain_found_pending = TRUE;
460*ef270ab1SKenneth D. Merry 		break;
461*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_LOST:
462*ef270ab1SKenneth D. Merry 		/* clear drec available
463*ef270ab1SKenneth D. Merry 		 * sm: unmark domain_found_pending */
464*ef270ab1SKenneth D. Merry 		domain->domain_found_pending = FALSE;
465*ef270ab1SKenneth D. Merry 		break;
466*ef270ab1SKenneth D. Merry 
467*ef270ab1SKenneth D. Merry 	default:
468*ef270ab1SKenneth D. Merry 		ocs_log_warn(domain->ocs, "%-20s %-20s not handled\n", funcname, ocs_sm_event_name(evt));
469*ef270ab1SKenneth D. Merry 		break;
470*ef270ab1SKenneth D. Merry 	}
471*ef270ab1SKenneth D. Merry 
472*ef270ab1SKenneth D. Merry 	return NULL;
473*ef270ab1SKenneth D. Merry }
474*ef270ab1SKenneth D. Merry 
475*ef270ab1SKenneth D. Merry #define std_domain_state_decl(...) \
476*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = NULL; \
477*ef270ab1SKenneth D. Merry 	ocs_t *ocs = NULL; \
478*ef270ab1SKenneth D. Merry 	\
479*ef270ab1SKenneth D. Merry 	ocs_assert(ctx, NULL); \
480*ef270ab1SKenneth D. Merry 	ocs_assert(ctx->app, NULL); \
481*ef270ab1SKenneth D. Merry 	domain = ctx->app; \
482*ef270ab1SKenneth D. Merry 	ocs_assert(domain->ocs, NULL); \
483*ef270ab1SKenneth D. Merry 	ocs = domain->ocs; \
484*ef270ab1SKenneth D. Merry 	ocs_assert(ocs->xport, NULL);
485*ef270ab1SKenneth D. Merry 
486*ef270ab1SKenneth D. Merry /**
487*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
488*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Initial state.
489*ef270ab1SKenneth D. Merry  *
490*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
491*ef270ab1SKenneth D. Merry  * The initial state for a domain. Each domain is initialized to
492*ef270ab1SKenneth D. Merry  * this state at start of day (SOD).
493*ef270ab1SKenneth D. Merry  *
494*ef270ab1SKenneth D. Merry  * @param ctx Domain state machine context.
495*ef270ab1SKenneth D. Merry  * @param evt Event to process.
496*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
497*ef270ab1SKenneth D. Merry  *
498*ef270ab1SKenneth D. Merry  * @return Returns NULL.
499*ef270ab1SKenneth D. Merry  */
500*ef270ab1SKenneth D. Merry 
501*ef270ab1SKenneth D. Merry void *
__ocs_domain_init(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)502*ef270ab1SKenneth D. Merry __ocs_domain_init(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
503*ef270ab1SKenneth D. Merry {
504*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
505*ef270ab1SKenneth D. Merry 
506*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
507*ef270ab1SKenneth D. Merry 
508*ef270ab1SKenneth D. Merry 	switch(evt) {
509*ef270ab1SKenneth D. Merry 	case OCS_EVT_ENTER:
510*ef270ab1SKenneth D. Merry 		domain->attached = 0;
511*ef270ab1SKenneth D. Merry 		break;
512*ef270ab1SKenneth D. Merry 
513*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FOUND: {
514*ef270ab1SKenneth D. Merry 		int32_t		vlan = 0;
515*ef270ab1SKenneth D. Merry 		uint32_t	i;
516*ef270ab1SKenneth D. Merry 		ocs_domain_record_t *drec = arg;
517*ef270ab1SKenneth D. Merry 		ocs_sport_t *sport;
518*ef270ab1SKenneth D. Merry 
519*ef270ab1SKenneth D. Merry 		uint64_t	my_wwnn = ocs->xport->req_wwnn;
520*ef270ab1SKenneth D. Merry 		uint64_t	my_wwpn = ocs->xport->req_wwpn;
521*ef270ab1SKenneth D. Merry 		uint64_t	be_wwpn;
522*ef270ab1SKenneth D. Merry 
523*ef270ab1SKenneth D. Merry 		/* For now, user must specify both port name and node name, or we let firmware
524*ef270ab1SKenneth D. Merry 		 * pick both (same as for vports).
525*ef270ab1SKenneth D. Merry 		 * TODO: do we want to allow setting only port name or only node name?
526*ef270ab1SKenneth D. Merry 		 */
527*ef270ab1SKenneth D. Merry 		if ((my_wwpn == 0) || (my_wwnn == 0)) {
528*ef270ab1SKenneth D. Merry 			ocs_log_debug(ocs, "using default hardware WWN configuration \n");
529*ef270ab1SKenneth D. Merry 			my_wwpn = ocs_get_wwn(&ocs->hw, OCS_HW_WWN_PORT);
530*ef270ab1SKenneth D. Merry 			my_wwnn = ocs_get_wwn(&ocs->hw, OCS_HW_WWN_NODE);
531*ef270ab1SKenneth D. Merry 		}
532*ef270ab1SKenneth D. Merry 
533*ef270ab1SKenneth D. Merry 		ocs_log_debug(ocs, "Creating base sport using WWPN %016" PRIx64 " WWNN %016" PRIx64 "\n",
534*ef270ab1SKenneth D. Merry 			my_wwpn, my_wwnn);
535*ef270ab1SKenneth D. Merry 
536*ef270ab1SKenneth D. Merry 		/* Allocate a sport and transition to __ocs_sport_allocated */
537*ef270ab1SKenneth D. Merry 		sport = ocs_sport_alloc(domain, my_wwpn, my_wwnn, UINT32_MAX, ocs->enable_ini, ocs->enable_tgt);
538*ef270ab1SKenneth D. Merry 
539*ef270ab1SKenneth D. Merry 		if (sport == NULL) {
540*ef270ab1SKenneth D. Merry 			ocs_log_err(ocs, "ocs_sport_alloc() failed\n");
541*ef270ab1SKenneth D. Merry 			break;
542*ef270ab1SKenneth D. Merry 		}
543*ef270ab1SKenneth D. Merry 		ocs_sm_transition(&sport->sm, __ocs_sport_allocated, NULL);
544*ef270ab1SKenneth D. Merry 
545*ef270ab1SKenneth D. Merry 		/* If domain is ethernet, then fetch the vlan id value */
546*ef270ab1SKenneth D. Merry 		if (drec->is_ethernet) {
547*ef270ab1SKenneth D. Merry 			vlan = ocs_bitmap_search((void *)drec->map.vlan, TRUE, 512 * 8);
548*ef270ab1SKenneth D. Merry 			if (vlan < 0) {
549*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "no VLAN id available (FCF=%d)\n",
550*ef270ab1SKenneth D. Merry 						drec->index);
551*ef270ab1SKenneth D. Merry 				break;
552*ef270ab1SKenneth D. Merry 			}
553*ef270ab1SKenneth D. Merry 		}
554*ef270ab1SKenneth D. Merry 
555*ef270ab1SKenneth D. Merry 		be_wwpn = ocs_htobe64(sport->wwpn);
556*ef270ab1SKenneth D. Merry 
557*ef270ab1SKenneth D. Merry 		/* allocate ocs_sli_port_t object for local port
558*ef270ab1SKenneth D. Merry 		 * Note: drec->fc_id is ALPA from read_topology only if loop
559*ef270ab1SKenneth D. Merry 		 */
560*ef270ab1SKenneth D. Merry 		if (ocs_hw_port_alloc(&ocs->hw, sport, NULL, (uint8_t *)&be_wwpn)) {
561*ef270ab1SKenneth D. Merry 			ocs_log_err(ocs, "Can't allocate port\n");
562*ef270ab1SKenneth D. Merry 			ocs_sport_free(sport);
563*ef270ab1SKenneth D. Merry 			break;
564*ef270ab1SKenneth D. Merry 		}
565*ef270ab1SKenneth D. Merry 
566*ef270ab1SKenneth D. Merry 		/* initialize domain object */
567*ef270ab1SKenneth D. Merry 		domain->is_loop = drec->is_loop;
568*ef270ab1SKenneth D. Merry 		domain->is_fc = drec->is_fc;
569*ef270ab1SKenneth D. Merry 
570*ef270ab1SKenneth D. Merry 		/*
571*ef270ab1SKenneth D. Merry 		 * If the loop position map includes ALPA == 0, then we are in a public loop (NL_PORT)
572*ef270ab1SKenneth D. Merry 		 * Note that the first element of the loopmap[] contains the count of elements, and if
573*ef270ab1SKenneth D. Merry 		 * ALPA == 0 is present, it will occupy the first location after the count.
574*ef270ab1SKenneth D. Merry 		 */
575*ef270ab1SKenneth D. Merry 		domain->is_nlport = drec->map.loop[1] == 0x00;
576*ef270ab1SKenneth D. Merry 
577*ef270ab1SKenneth D. Merry 		if (domain->is_loop) {
578*ef270ab1SKenneth D. Merry 			ocs_log_debug(ocs, "%s fc_id=%#x speed=%d\n",
579*ef270ab1SKenneth D. Merry 					drec->is_loop ? (domain->is_nlport ? "public-loop" : "loop") : "other",
580*ef270ab1SKenneth D. Merry 					drec->fc_id, drec->speed);
581*ef270ab1SKenneth D. Merry 
582*ef270ab1SKenneth D. Merry 			sport->fc_id = drec->fc_id;
583*ef270ab1SKenneth D. Merry 			sport->topology = OCS_SPORT_TOPOLOGY_LOOP;
584*ef270ab1SKenneth D. Merry 			ocs_snprintf(sport->display_name, sizeof(sport->display_name), "s%06x", drec->fc_id);
585*ef270ab1SKenneth D. Merry 
586*ef270ab1SKenneth D. Merry 			if (ocs->enable_ini) {
587*ef270ab1SKenneth D. Merry 				uint32_t count = drec->map.loop[0];
588*ef270ab1SKenneth D. Merry 				ocs_log_debug(ocs, "%d position map entries\n", count);
589*ef270ab1SKenneth D. Merry 				for (i = 1; i <= count; i++) {
590*ef270ab1SKenneth D. Merry 					if (drec->map.loop[i] != drec->fc_id) {
591*ef270ab1SKenneth D. Merry 						ocs_node_t *node;
592*ef270ab1SKenneth D. Merry 
593*ef270ab1SKenneth D. Merry 						ocs_log_debug(ocs, "%#x -> %#x\n",
594*ef270ab1SKenneth D. Merry 								drec->fc_id, drec->map.loop[i]);
595*ef270ab1SKenneth D. Merry 						node = ocs_node_alloc(sport, drec->map.loop[i], FALSE, TRUE);
596*ef270ab1SKenneth D. Merry 						if (node == NULL) {
597*ef270ab1SKenneth D. Merry 							ocs_log_err(ocs, "ocs_node_alloc() failed\n");
598*ef270ab1SKenneth D. Merry 							break;
599*ef270ab1SKenneth D. Merry 						}
600*ef270ab1SKenneth D. Merry 						ocs_node_transition(node, __ocs_d_wait_loop, NULL);
601*ef270ab1SKenneth D. Merry 					}
602*ef270ab1SKenneth D. Merry 				}
603*ef270ab1SKenneth D. Merry 			}
604*ef270ab1SKenneth D. Merry 		}
605*ef270ab1SKenneth D. Merry 
606*ef270ab1SKenneth D. Merry 		/* Initiate HW domain alloc */
607*ef270ab1SKenneth D. Merry 		if (ocs_hw_domain_alloc(&ocs->hw, domain, drec->index, vlan)) {
608*ef270ab1SKenneth D. Merry 			ocs_log_err(ocs, "Failed to initiate HW domain allocation\n");
609*ef270ab1SKenneth D. Merry 			break;
610*ef270ab1SKenneth D. Merry 		}
611*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_wait_alloc, arg);
612*ef270ab1SKenneth D. Merry 		break;
613*ef270ab1SKenneth D. Merry 	}
614*ef270ab1SKenneth D. Merry 	default:
615*ef270ab1SKenneth D. Merry 		__ocs_domain_common(__func__, ctx, evt, arg);
616*ef270ab1SKenneth D. Merry 		return NULL;
617*ef270ab1SKenneth D. Merry 	}
618*ef270ab1SKenneth D. Merry 
619*ef270ab1SKenneth D. Merry 	return NULL;
620*ef270ab1SKenneth D. Merry }
621*ef270ab1SKenneth D. Merry 
622*ef270ab1SKenneth D. Merry /**
623*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
624*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Wait for the domain allocation to complete.
625*ef270ab1SKenneth D. Merry  *
626*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
627*ef270ab1SKenneth D. Merry  * Waits for the domain state to be allocated. After the HW domain
628*ef270ab1SKenneth D. Merry  * allocation process has been initiated, this state waits for
629*ef270ab1SKenneth D. Merry  * that process to complete (i.e. a domain-alloc-ok event).
630*ef270ab1SKenneth D. Merry  *
631*ef270ab1SKenneth D. Merry  * @param ctx Domain state machine context.
632*ef270ab1SKenneth D. Merry  * @param evt Event to process.
633*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
634*ef270ab1SKenneth D. Merry  *
635*ef270ab1SKenneth D. Merry  * @return Returns NULL.
636*ef270ab1SKenneth D. Merry  */
637*ef270ab1SKenneth D. Merry 
638*ef270ab1SKenneth D. Merry void *
__ocs_domain_wait_alloc(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)639*ef270ab1SKenneth D. Merry __ocs_domain_wait_alloc(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
640*ef270ab1SKenneth D. Merry {
641*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
642*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
643*ef270ab1SKenneth D. Merry 
644*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
645*ef270ab1SKenneth D. Merry 
646*ef270ab1SKenneth D. Merry 	switch(evt) {
647*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ALLOC_OK: {
648*ef270ab1SKenneth D. Merry 		char prop_buf[32];
649*ef270ab1SKenneth D. Merry 		uint64_t wwn_bump = 0;
650*ef270ab1SKenneth D. Merry 		fc_plogi_payload_t *sp;
651*ef270ab1SKenneth D. Merry 
652*ef270ab1SKenneth D. Merry 		if (ocs_get_property("wwn_bump", prop_buf, sizeof(prop_buf)) == 0) {
653*ef270ab1SKenneth D. Merry 			wwn_bump = ocs_strtoull(prop_buf, 0, 0);
654*ef270ab1SKenneth D. Merry 		}
655*ef270ab1SKenneth D. Merry 
656*ef270ab1SKenneth D. Merry 		sport = domain->sport;
657*ef270ab1SKenneth D. Merry 		ocs_assert(sport, NULL);
658*ef270ab1SKenneth D. Merry 		sp = (fc_plogi_payload_t*) sport->service_params;
659*ef270ab1SKenneth D. Merry 
660*ef270ab1SKenneth D. Merry 		/* Save the domain service parameters */
661*ef270ab1SKenneth D. Merry 		ocs_memcpy(domain->service_params + 4, domain->dma.virt, sizeof(fc_plogi_payload_t) - 4);
662*ef270ab1SKenneth D. Merry 		ocs_memcpy(sport->service_params + 4, domain->dma.virt, sizeof(fc_plogi_payload_t) - 4);
663*ef270ab1SKenneth D. Merry 
664*ef270ab1SKenneth D. Merry 		/* If we're in fabric emulation mode, the flogi service parameters have not been setup yet,
665*ef270ab1SKenneth D. Merry 		 * so we need some reasonable BB credit value
666*ef270ab1SKenneth D. Merry 		 */
667*ef270ab1SKenneth D. Merry 		if (domain->femul_enable) {
668*ef270ab1SKenneth D. Merry 			ocs_memcpy(domain->flogi_service_params + 4, domain->service_params + 4, sizeof(fc_plogi_payload_t) - 4);
669*ef270ab1SKenneth D. Merry 		}
670*ef270ab1SKenneth D. Merry 
671*ef270ab1SKenneth D. Merry 		/* Update the sport's service parameters, user might have specified non-default names */
672*ef270ab1SKenneth D. Merry 		sp->port_name_hi = ocs_htobe32((uint32_t) (sport->wwpn >> 32ll));
673*ef270ab1SKenneth D. Merry 		sp->port_name_lo = ocs_htobe32((uint32_t) sport->wwpn);
674*ef270ab1SKenneth D. Merry 		sp->node_name_hi = ocs_htobe32((uint32_t) (sport->wwnn >> 32ll));
675*ef270ab1SKenneth D. Merry 		sp->node_name_lo = ocs_htobe32((uint32_t) sport->wwnn);
676*ef270ab1SKenneth D. Merry 
677*ef270ab1SKenneth D. Merry 		if (wwn_bump) {
678*ef270ab1SKenneth D. Merry 			sp->port_name_lo = ocs_htobe32(ocs_be32toh(sp->port_name_lo) ^ ((uint32_t)(wwn_bump)));
679*ef270ab1SKenneth D. Merry 			sp->port_name_hi = ocs_htobe32(ocs_be32toh(sp->port_name_hi) ^ ((uint32_t)(wwn_bump >> 32)));
680*ef270ab1SKenneth D. Merry 			sp->node_name_lo = ocs_htobe32(ocs_be32toh(sp->node_name_lo) ^ ((uint32_t)(wwn_bump)));
681*ef270ab1SKenneth D. Merry 			sp->node_name_hi = ocs_htobe32(ocs_be32toh(sp->node_name_hi) ^ ((uint32_t)(wwn_bump >> 32)));
682*ef270ab1SKenneth D. Merry 			ocs_log_info(ocs, "Overriding WWN\n");
683*ef270ab1SKenneth D. Merry 		}
684*ef270ab1SKenneth D. Merry 
685*ef270ab1SKenneth D. Merry 		/* Take the loop topology path, unless we are an NL_PORT (public loop) */
686*ef270ab1SKenneth D. Merry 		if (domain->is_loop && !domain->is_nlport) {
687*ef270ab1SKenneth D. Merry 			/*
688*ef270ab1SKenneth D. Merry 			 * For loop, we already have our FC ID and don't need fabric login.
689*ef270ab1SKenneth D. Merry 			 * Transition to the allocated state and post an event to attach to
690*ef270ab1SKenneth D. Merry 			 * the domain. Note that this breaks the normal action/transition
691*ef270ab1SKenneth D. Merry 			 * pattern here to avoid a race with the domain attach callback.
692*ef270ab1SKenneth D. Merry 			 */
693*ef270ab1SKenneth D. Merry 			/* sm: is_loop / domain_attach */
694*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_allocated, NULL);
695*ef270ab1SKenneth D. Merry 			__ocs_domain_attach_internal(domain, sport->fc_id);
696*ef270ab1SKenneth D. Merry 			break;
697*ef270ab1SKenneth D. Merry 		} else {
698*ef270ab1SKenneth D. Merry 			ocs_node_t *node;
699*ef270ab1SKenneth D. Merry 
700*ef270ab1SKenneth D. Merry 			/* alloc fabric node, send FLOGI */
701*ef270ab1SKenneth D. Merry 			node = ocs_node_find(sport, FC_ADDR_FABRIC);
702*ef270ab1SKenneth D. Merry 			if (node) {
703*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "Hmmmm ... Fabric Controller node already exists\n");
704*ef270ab1SKenneth D. Merry 				break;
705*ef270ab1SKenneth D. Merry 			}
706*ef270ab1SKenneth D. Merry 			node = ocs_node_alloc(sport, FC_ADDR_FABRIC, FALSE, FALSE);
707*ef270ab1SKenneth D. Merry 			if (!node) {
708*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "Error: ocs_node_alloc() failed\n");
709*ef270ab1SKenneth D. Merry 			} else {
710*ef270ab1SKenneth D. Merry 				if (ocs->nodedb_mask & OCS_NODEDB_PAUSE_FABRIC_LOGIN) {
711*ef270ab1SKenneth D. Merry 					ocs_node_pause(node, __ocs_fabric_init);
712*ef270ab1SKenneth D. Merry 				} else {
713*ef270ab1SKenneth D. Merry 					ocs_node_transition(node, __ocs_fabric_init, NULL);
714*ef270ab1SKenneth D. Merry 				}
715*ef270ab1SKenneth D. Merry 			}
716*ef270ab1SKenneth D. Merry 			/* Accept frames */
717*ef270ab1SKenneth D. Merry 			domain->req_accept_frames = 1;
718*ef270ab1SKenneth D. Merry 		}
719*ef270ab1SKenneth D. Merry 		/* sm: start fabric logins */
720*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_allocated, NULL);
721*ef270ab1SKenneth D. Merry 		break;
722*ef270ab1SKenneth D. Merry 	}
723*ef270ab1SKenneth D. Merry 
724*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ALLOC_FAIL:
725*ef270ab1SKenneth D. Merry 		/* TODO: hw/device reset */
726*ef270ab1SKenneth D. Merry 		ocs_log_err(ocs, "%s recv'd waiting for DOMAIN_ALLOC_OK; shutting down domain\n",
727*ef270ab1SKenneth D. Merry 			ocs_sm_event_name(evt));
728*ef270ab1SKenneth D. Merry 		domain->req_domain_free = 1;
729*ef270ab1SKenneth D. Merry 		break;
730*ef270ab1SKenneth D. Merry 
731*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FOUND:
732*ef270ab1SKenneth D. Merry 		/* Should not happen */
733*ef270ab1SKenneth D. Merry 		ocs_assert(evt, NULL);
734*ef270ab1SKenneth D. Merry 		break;
735*ef270ab1SKenneth D. Merry 
736*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_LOST:
737*ef270ab1SKenneth D. Merry 		ocs_log_debug(ocs, "%s received while waiting for ocs_hw_domain_alloc() to complete\n", ocs_sm_event_name(evt));
738*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_wait_domain_lost, NULL);
739*ef270ab1SKenneth D. Merry 		break;
740*ef270ab1SKenneth D. Merry 
741*ef270ab1SKenneth D. Merry 	default:
742*ef270ab1SKenneth D. Merry 		__ocs_domain_common(__func__, ctx, evt, arg);
743*ef270ab1SKenneth D. Merry 		return NULL;
744*ef270ab1SKenneth D. Merry 	}
745*ef270ab1SKenneth D. Merry 
746*ef270ab1SKenneth D. Merry 	return NULL;
747*ef270ab1SKenneth D. Merry }
748*ef270ab1SKenneth D. Merry 
749*ef270ab1SKenneth D. Merry /**
750*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
751*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Wait for the domain attach request.
752*ef270ab1SKenneth D. Merry  *
753*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
754*ef270ab1SKenneth D. Merry  * In this state, the domain has been allocated and is waiting for a domain attach request.
755*ef270ab1SKenneth D. Merry  * The attach request comes from a node instance completing the fabric login,
756*ef270ab1SKenneth D. Merry  * or from a point-to-point negotiation and login.
757*ef270ab1SKenneth D. Merry  *
758*ef270ab1SKenneth D. Merry  * @param ctx Remote node state machine context.
759*ef270ab1SKenneth D. Merry  * @param evt Event to process.
760*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
761*ef270ab1SKenneth D. Merry  *
762*ef270ab1SKenneth D. Merry  * @return Returns NULL.
763*ef270ab1SKenneth D. Merry  */
764*ef270ab1SKenneth D. Merry 
765*ef270ab1SKenneth D. Merry void *
__ocs_domain_allocated(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)766*ef270ab1SKenneth D. Merry __ocs_domain_allocated(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
767*ef270ab1SKenneth D. Merry {
768*ef270ab1SKenneth D. Merry 	int32_t rc = 0;
769*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
770*ef270ab1SKenneth D. Merry 
771*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
772*ef270ab1SKenneth D. Merry 
773*ef270ab1SKenneth D. Merry 	switch(evt) {
774*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_REQ_ATTACH: {
775*ef270ab1SKenneth D. Merry 		uint32_t fc_id;
776*ef270ab1SKenneth D. Merry 
777*ef270ab1SKenneth D. Merry 		ocs_assert(arg, NULL);
778*ef270ab1SKenneth D. Merry 
779*ef270ab1SKenneth D. Merry 		fc_id = *((uint32_t*)arg);
780*ef270ab1SKenneth D. Merry 		ocs_log_debug(ocs, "Requesting hw domain attach fc_id x%x\n", fc_id);
781*ef270ab1SKenneth D. Merry 		/* Update sport lookup */
782*ef270ab1SKenneth D. Merry 		ocs_lock(&domain->lookup_lock);
783*ef270ab1SKenneth D. Merry 			spv_set(domain->lookup, fc_id, domain->sport);
784*ef270ab1SKenneth D. Merry 		ocs_unlock(&domain->lookup_lock);
785*ef270ab1SKenneth D. Merry 
786*ef270ab1SKenneth D. Merry 		/* Update display name for the sport */
787*ef270ab1SKenneth D. Merry 		ocs_node_fcid_display(fc_id, domain->sport->display_name, sizeof(domain->sport->display_name));
788*ef270ab1SKenneth D. Merry 
789*ef270ab1SKenneth D. Merry 		/* Issue domain attach call */
790*ef270ab1SKenneth D. Merry 		rc = ocs_hw_domain_attach(&ocs->hw, domain, fc_id);
791*ef270ab1SKenneth D. Merry 		if (rc) {
792*ef270ab1SKenneth D. Merry 			ocs_log_err(ocs, "ocs_hw_domain_attach failed: %d\n", rc);
793*ef270ab1SKenneth D. Merry 			return NULL;
794*ef270ab1SKenneth D. Merry 		}
795*ef270ab1SKenneth D. Merry 		/* sm: / domain_attach */
796*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_wait_attach, NULL);
797*ef270ab1SKenneth D. Merry 		break;
798*ef270ab1SKenneth D. Merry 	}
799*ef270ab1SKenneth D. Merry 
800*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FOUND:
801*ef270ab1SKenneth D. Merry 		/* Should not happen */
802*ef270ab1SKenneth D. Merry 		ocs_assert(evt, NULL);
803*ef270ab1SKenneth D. Merry 		break;
804*ef270ab1SKenneth D. Merry 
805*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_LOST: {
806*ef270ab1SKenneth D. Merry 		int32_t rc;
807*ef270ab1SKenneth D. Merry 		ocs_log_debug(ocs, "%s received while waiting for OCS_EVT_DOMAIN_REQ_ATTACH\n",
808*ef270ab1SKenneth D. Merry 			ocs_sm_event_name(evt));
809*ef270ab1SKenneth D. Merry 		ocs_domain_lock(domain);
810*ef270ab1SKenneth D. Merry 		if (!ocs_list_empty(&domain->sport_list)) {
811*ef270ab1SKenneth D. Merry 			/* if there are sports, transition to wait state and
812*ef270ab1SKenneth D. Merry 			 * send shutdown to each sport */
813*ef270ab1SKenneth D. Merry 			ocs_sport_t	*sport = NULL;
814*ef270ab1SKenneth D. Merry 			ocs_sport_t	*sport_next = NULL;
815*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_wait_sports_free, NULL);
816*ef270ab1SKenneth D. Merry 			ocs_list_foreach_safe(&domain->sport_list, sport, sport_next) {
817*ef270ab1SKenneth D. Merry 				ocs_sm_post_event(&sport->sm, OCS_EVT_SHUTDOWN, NULL);
818*ef270ab1SKenneth D. Merry 			}
819*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
820*ef270ab1SKenneth D. Merry 		} else {
821*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
822*ef270ab1SKenneth D. Merry 			/* no sports exist, free domain */
823*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_wait_shutdown, NULL);
824*ef270ab1SKenneth D. Merry 			rc = ocs_hw_domain_free(&ocs->hw, domain);
825*ef270ab1SKenneth D. Merry 			if (rc) {
826*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "ocs_hw_domain_free() failed: %d\n", rc);
827*ef270ab1SKenneth D. Merry 				/* TODO: hw/device reset needed */
828*ef270ab1SKenneth D. Merry 			}
829*ef270ab1SKenneth D. Merry 		}
830*ef270ab1SKenneth D. Merry 
831*ef270ab1SKenneth D. Merry 		break;
832*ef270ab1SKenneth D. Merry 	}
833*ef270ab1SKenneth D. Merry 
834*ef270ab1SKenneth D. Merry 	default:
835*ef270ab1SKenneth D. Merry 		__ocs_domain_common(__func__, ctx, evt, arg);
836*ef270ab1SKenneth D. Merry 		return NULL;
837*ef270ab1SKenneth D. Merry 	}
838*ef270ab1SKenneth D. Merry 
839*ef270ab1SKenneth D. Merry 	return NULL;
840*ef270ab1SKenneth D. Merry }
841*ef270ab1SKenneth D. Merry 
842*ef270ab1SKenneth D. Merry /**
843*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
844*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Wait for the HW domain attach to complete.
845*ef270ab1SKenneth D. Merry  *
846*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
847*ef270ab1SKenneth D. Merry  * Waits for the HW domain attach to complete. Forwards attach ok event to the
848*ef270ab1SKenneth D. Merry  * fabric node state machine.
849*ef270ab1SKenneth D. Merry  *
850*ef270ab1SKenneth D. Merry  * @param ctx Remote node state machine context.
851*ef270ab1SKenneth D. Merry  * @param evt Event to process.
852*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
853*ef270ab1SKenneth D. Merry  *
854*ef270ab1SKenneth D. Merry  * @return Returns NULL.
855*ef270ab1SKenneth D. Merry  */
856*ef270ab1SKenneth D. Merry 
857*ef270ab1SKenneth D. Merry void *
__ocs_domain_wait_attach(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)858*ef270ab1SKenneth D. Merry __ocs_domain_wait_attach(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
859*ef270ab1SKenneth D. Merry {
860*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
861*ef270ab1SKenneth D. Merry 
862*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
863*ef270ab1SKenneth D. Merry 
864*ef270ab1SKenneth D. Merry 	switch(evt) {
865*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ATTACH_OK: {
866*ef270ab1SKenneth D. Merry 		ocs_node_t *node = NULL;
867*ef270ab1SKenneth D. Merry 		ocs_node_t *next_node = NULL;
868*ef270ab1SKenneth D. Merry 		ocs_sport_t *sport;
869*ef270ab1SKenneth D. Merry 		ocs_sport_t *next_sport;
870*ef270ab1SKenneth D. Merry 
871*ef270ab1SKenneth D. Merry 		/* Mark as attached */
872*ef270ab1SKenneth D. Merry 		domain->attached = 1;
873*ef270ab1SKenneth D. Merry 
874*ef270ab1SKenneth D. Merry 		/* Register with SCSI API */
875*ef270ab1SKenneth D. Merry 		if (ocs->enable_tgt)
876*ef270ab1SKenneth D. Merry 			ocs_scsi_tgt_new_domain(domain);
877*ef270ab1SKenneth D. Merry 		if (ocs->enable_ini)
878*ef270ab1SKenneth D. Merry 			ocs_scsi_ini_new_domain(domain);
879*ef270ab1SKenneth D. Merry 
880*ef270ab1SKenneth D. Merry 		/* Transition to ready */
881*ef270ab1SKenneth D. Merry 		/* sm: / forward event to all sports and nodes */
882*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_ready, NULL);
883*ef270ab1SKenneth D. Merry 
884*ef270ab1SKenneth D. Merry 		/* We have an FCFI, so we can accept frames */
885*ef270ab1SKenneth D. Merry 		domain->req_accept_frames = 1;
886*ef270ab1SKenneth D. Merry 		/* Set domain notify pending state to avoid duplicate domain event post */
887*ef270ab1SKenneth D. Merry 		domain->domain_notify_pend = 1;
888*ef270ab1SKenneth D. Merry 
889*ef270ab1SKenneth D. Merry 		/* Notify all nodes that the domain attach request has completed
890*ef270ab1SKenneth D. Merry 		 * Note: sport will have already received notification of sport attached
891*ef270ab1SKenneth D. Merry 		 * as a result of the HW's port attach.
892*ef270ab1SKenneth D. Merry 		 */
893*ef270ab1SKenneth D. Merry 		ocs_domain_lock(domain);
894*ef270ab1SKenneth D. Merry 			ocs_list_foreach_safe(&domain->sport_list, sport, next_sport) {
895*ef270ab1SKenneth D. Merry 				ocs_sport_lock(sport);
896*ef270ab1SKenneth D. Merry 					ocs_list_foreach_safe(&sport->node_list, node, next_node) {
897*ef270ab1SKenneth D. Merry 						ocs_node_post_event(node, OCS_EVT_DOMAIN_ATTACH_OK, NULL);
898*ef270ab1SKenneth D. Merry 					}
899*ef270ab1SKenneth D. Merry 				ocs_sport_unlock(sport);
900*ef270ab1SKenneth D. Merry 			}
901*ef270ab1SKenneth D. Merry 		ocs_domain_unlock(domain);
902*ef270ab1SKenneth D. Merry 		domain->domain_notify_pend = 0;
903*ef270ab1SKenneth D. Merry 		break;
904*ef270ab1SKenneth D. Merry 	}
905*ef270ab1SKenneth D. Merry 
906*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ATTACH_FAIL:
907*ef270ab1SKenneth D. Merry 		ocs_log_debug(ocs, "%s received while waiting for hw attach to complete\n", ocs_sm_event_name(evt));
908*ef270ab1SKenneth D. Merry 		/* TODO: hw/device reset */
909*ef270ab1SKenneth D. Merry 		break;
910*ef270ab1SKenneth D. Merry 
911*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FOUND:
912*ef270ab1SKenneth D. Merry 		/* Should not happen */
913*ef270ab1SKenneth D. Merry 		ocs_assert(evt, NULL);
914*ef270ab1SKenneth D. Merry 		break;
915*ef270ab1SKenneth D. Merry 
916*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_LOST:
917*ef270ab1SKenneth D. Merry 		/* Domain lost while waiting for an attach to complete, go to a state that waits for
918*ef270ab1SKenneth D. Merry 		 * the domain attach to complete, then handle domain lost
919*ef270ab1SKenneth D. Merry 		 */
920*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_wait_domain_lost, NULL);
921*ef270ab1SKenneth D. Merry 		break;
922*ef270ab1SKenneth D. Merry 
923*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_REQ_ATTACH:
924*ef270ab1SKenneth D. Merry 		/* In P2P we can get an attach request from the other FLOGI path, so drop this one */
925*ef270ab1SKenneth D. Merry 		break;
926*ef270ab1SKenneth D. Merry 
927*ef270ab1SKenneth D. Merry 	default:
928*ef270ab1SKenneth D. Merry 		__ocs_domain_common(__func__, ctx, evt, arg);
929*ef270ab1SKenneth D. Merry 		return NULL;
930*ef270ab1SKenneth D. Merry 	}
931*ef270ab1SKenneth D. Merry 
932*ef270ab1SKenneth D. Merry 	return NULL;
933*ef270ab1SKenneth D. Merry }
934*ef270ab1SKenneth D. Merry 
935*ef270ab1SKenneth D. Merry /**
936*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
937*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Ready state.
938*ef270ab1SKenneth D. Merry  *
939*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
940*ef270ab1SKenneth D. Merry  * This is a domain ready state. It waits for a domain-lost event, and initiates shutdown.
941*ef270ab1SKenneth D. Merry  *
942*ef270ab1SKenneth D. Merry  * @param ctx Remote node state machine context.
943*ef270ab1SKenneth D. Merry  * @param evt Event to process.
944*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
945*ef270ab1SKenneth D. Merry  *
946*ef270ab1SKenneth D. Merry  * @return Returns NULL.
947*ef270ab1SKenneth D. Merry  */
948*ef270ab1SKenneth D. Merry 
949*ef270ab1SKenneth D. Merry void *
__ocs_domain_ready(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)950*ef270ab1SKenneth D. Merry __ocs_domain_ready(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
951*ef270ab1SKenneth D. Merry {
952*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
953*ef270ab1SKenneth D. Merry 
954*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
955*ef270ab1SKenneth D. Merry 
956*ef270ab1SKenneth D. Merry 	switch(evt) {
957*ef270ab1SKenneth D. Merry 	case OCS_EVT_ENTER: {
958*ef270ab1SKenneth D. Merry 		/* start any pending vports */
959*ef270ab1SKenneth D. Merry 		if (ocs_vport_start(domain)) {
960*ef270ab1SKenneth D. Merry 			ocs_log_debug(domain->ocs, "ocs_vport_start() did not start all vports\n");
961*ef270ab1SKenneth D. Merry 		}
962*ef270ab1SKenneth D. Merry 		break;
963*ef270ab1SKenneth D. Merry 	}
964*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_LOST: {
965*ef270ab1SKenneth D. Merry 		int32_t rc;
966*ef270ab1SKenneth D. Merry 		ocs_domain_lock(domain);
967*ef270ab1SKenneth D. Merry 		if (!ocs_list_empty(&domain->sport_list)) {
968*ef270ab1SKenneth D. Merry 			/* if there are sports, transition to wait state and send
969*ef270ab1SKenneth D. Merry 			* shutdown to each sport */
970*ef270ab1SKenneth D. Merry 			ocs_sport_t	*sport = NULL;
971*ef270ab1SKenneth D. Merry 			ocs_sport_t	*sport_next = NULL;
972*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_wait_sports_free, NULL);
973*ef270ab1SKenneth D. Merry 			ocs_list_foreach_safe(&domain->sport_list, sport, sport_next) {
974*ef270ab1SKenneth D. Merry 				ocs_sm_post_event(&sport->sm, OCS_EVT_SHUTDOWN, NULL);
975*ef270ab1SKenneth D. Merry 			}
976*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
977*ef270ab1SKenneth D. Merry 		} else {
978*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
979*ef270ab1SKenneth D. Merry 			/* no sports exist, free domain */
980*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_wait_shutdown, NULL);
981*ef270ab1SKenneth D. Merry 			rc = ocs_hw_domain_free(&ocs->hw, domain);
982*ef270ab1SKenneth D. Merry 			if (rc) {
983*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "ocs_hw_domain_free() failed: %d\n", rc);
984*ef270ab1SKenneth D. Merry 				/* TODO: hw/device reset needed */
985*ef270ab1SKenneth D. Merry 			}
986*ef270ab1SKenneth D. Merry 		}
987*ef270ab1SKenneth D. Merry 		break;
988*ef270ab1SKenneth D. Merry 	}
989*ef270ab1SKenneth D. Merry 
990*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FOUND:
991*ef270ab1SKenneth D. Merry 		/* Should not happen */
992*ef270ab1SKenneth D. Merry 		ocs_assert(evt, NULL);
993*ef270ab1SKenneth D. Merry 		break;
994*ef270ab1SKenneth D. Merry 
995*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_REQ_ATTACH: {
996*ef270ab1SKenneth D. Merry 		/* can happen during p2p */
997*ef270ab1SKenneth D. Merry 		uint32_t fc_id;
998*ef270ab1SKenneth D. Merry 
999*ef270ab1SKenneth D. Merry 		ocs_assert(arg, NULL);
1000*ef270ab1SKenneth D. Merry 		fc_id = *((uint32_t*)arg);
1001*ef270ab1SKenneth D. Merry 
1002*ef270ab1SKenneth D. Merry 		/* Assume that the domain is attached */
1003*ef270ab1SKenneth D. Merry 		ocs_assert(domain->attached, NULL);
1004*ef270ab1SKenneth D. Merry 
1005*ef270ab1SKenneth D. Merry 		/* Verify that the requested FC_ID is the same as the one we're working with */
1006*ef270ab1SKenneth D. Merry 		ocs_assert(domain->sport->fc_id == fc_id, NULL);
1007*ef270ab1SKenneth D. Merry 		break;
1008*ef270ab1SKenneth D. Merry 	}
1009*ef270ab1SKenneth D. Merry 
1010*ef270ab1SKenneth D. Merry 	default:
1011*ef270ab1SKenneth D. Merry 		__ocs_domain_common(__func__, ctx, evt, arg);
1012*ef270ab1SKenneth D. Merry 		return NULL;
1013*ef270ab1SKenneth D. Merry 	}
1014*ef270ab1SKenneth D. Merry 
1015*ef270ab1SKenneth D. Merry 	return NULL;
1016*ef270ab1SKenneth D. Merry }
1017*ef270ab1SKenneth D. Merry 
1018*ef270ab1SKenneth D. Merry /**
1019*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
1020*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Wait for nodes to free prior to the domain shutdown.
1021*ef270ab1SKenneth D. Merry  *
1022*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1023*ef270ab1SKenneth D. Merry  * All nodes are freed, and ready for a domain shutdown.
1024*ef270ab1SKenneth D. Merry  *
1025*ef270ab1SKenneth D. Merry  * @param ctx Remote node sm context.
1026*ef270ab1SKenneth D. Merry  * @param evt Event to process.
1027*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
1028*ef270ab1SKenneth D. Merry  *
1029*ef270ab1SKenneth D. Merry  * @return Returns NULL.
1030*ef270ab1SKenneth D. Merry  */
1031*ef270ab1SKenneth D. Merry 
1032*ef270ab1SKenneth D. Merry void *
__ocs_domain_wait_sports_free(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)1033*ef270ab1SKenneth D. Merry __ocs_domain_wait_sports_free(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1034*ef270ab1SKenneth D. Merry {
1035*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
1036*ef270ab1SKenneth D. Merry 
1037*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
1038*ef270ab1SKenneth D. Merry 
1039*ef270ab1SKenneth D. Merry 	switch(evt) {
1040*ef270ab1SKenneth D. Merry 	case OCS_EVT_ALL_CHILD_NODES_FREE: {
1041*ef270ab1SKenneth D. Merry 		int32_t rc;
1042*ef270ab1SKenneth D. Merry 
1043*ef270ab1SKenneth D. Merry 		/* sm: ocs_hw_domain_free */
1044*ef270ab1SKenneth D. Merry 		ocs_sm_transition(ctx, __ocs_domain_wait_shutdown, NULL);
1045*ef270ab1SKenneth D. Merry 
1046*ef270ab1SKenneth D. Merry 		/* Request ocs_hw_domain_free and wait for completion */
1047*ef270ab1SKenneth D. Merry 		rc = ocs_hw_domain_free(&ocs->hw, domain);
1048*ef270ab1SKenneth D. Merry 		if (rc) {
1049*ef270ab1SKenneth D. Merry 			ocs_log_err(ocs, "ocs_hw_domain_free() failed: %d\n", rc);
1050*ef270ab1SKenneth D. Merry 		}
1051*ef270ab1SKenneth D. Merry 		break;
1052*ef270ab1SKenneth D. Merry 	}
1053*ef270ab1SKenneth D. Merry 	default:
1054*ef270ab1SKenneth D. Merry 		__ocs_domain_common_shutdown(__func__, ctx, evt, arg);
1055*ef270ab1SKenneth D. Merry 		return NULL;
1056*ef270ab1SKenneth D. Merry 	}
1057*ef270ab1SKenneth D. Merry 
1058*ef270ab1SKenneth D. Merry 	return NULL;
1059*ef270ab1SKenneth D. Merry }
1060*ef270ab1SKenneth D. Merry 
1061*ef270ab1SKenneth D. Merry /**
1062*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
1063*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Complete the domain shutdown.
1064*ef270ab1SKenneth D. Merry  *
1065*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1066*ef270ab1SKenneth D. Merry  * Waits for a HW domain free to complete.
1067*ef270ab1SKenneth D. Merry  *
1068*ef270ab1SKenneth D. Merry  * @param ctx Remote node state machine context.
1069*ef270ab1SKenneth D. Merry  * @param evt Event to process.
1070*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
1071*ef270ab1SKenneth D. Merry  *
1072*ef270ab1SKenneth D. Merry  * @return Returns NULL.
1073*ef270ab1SKenneth D. Merry  */
1074*ef270ab1SKenneth D. Merry 
1075*ef270ab1SKenneth D. Merry void *
__ocs_domain_wait_shutdown(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)1076*ef270ab1SKenneth D. Merry __ocs_domain_wait_shutdown(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1077*ef270ab1SKenneth D. Merry {
1078*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
1079*ef270ab1SKenneth D. Merry 
1080*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
1081*ef270ab1SKenneth D. Merry 
1082*ef270ab1SKenneth D. Merry 	switch(evt) {
1083*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_FREE_OK: {
1084*ef270ab1SKenneth D. Merry 		if (ocs->enable_ini)
1085*ef270ab1SKenneth D. Merry 			ocs_scsi_ini_del_domain(domain);
1086*ef270ab1SKenneth D. Merry 		if (ocs->enable_tgt)
1087*ef270ab1SKenneth D. Merry 			ocs_scsi_tgt_del_domain(domain);
1088*ef270ab1SKenneth D. Merry 
1089*ef270ab1SKenneth D. Merry 		/* sm: domain_free */
1090*ef270ab1SKenneth D. Merry 		if (domain->domain_found_pending) {
1091*ef270ab1SKenneth D. Merry 			/* save fcf_wwn and drec from this domain, free current domain and allocate
1092*ef270ab1SKenneth D. Merry 			 * a new one with the same fcf_wwn
1093*ef270ab1SKenneth D. Merry 			 * TODO: could use a SLI-4 "re-register VPI" operation here
1094*ef270ab1SKenneth D. Merry 			 */
1095*ef270ab1SKenneth D. Merry 			uint64_t fcf_wwn = domain->fcf_wwn;
1096*ef270ab1SKenneth D. Merry 			ocs_domain_record_t drec = domain->pending_drec;
1097*ef270ab1SKenneth D. Merry 
1098*ef270ab1SKenneth D. Merry 			ocs_log_debug(ocs, "Reallocating domain\n");
1099*ef270ab1SKenneth D. Merry 			domain->req_domain_free = 1;
1100*ef270ab1SKenneth D. Merry 			domain = ocs_domain_alloc(ocs, fcf_wwn);
1101*ef270ab1SKenneth D. Merry 
1102*ef270ab1SKenneth D. Merry 			if (domain == NULL) {
1103*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "ocs_domain_alloc() failed\n");
1104*ef270ab1SKenneth D. Merry 				/* TODO: hw/device reset needed */
1105*ef270ab1SKenneth D. Merry 				return NULL;
1106*ef270ab1SKenneth D. Merry 			}
1107*ef270ab1SKenneth D. Merry 			/*
1108*ef270ab1SKenneth D. Merry 			 * got a new domain; at this point, there are at least two domains
1109*ef270ab1SKenneth D. Merry 			 * once the req_domain_free flag is processed, the associated domain
1110*ef270ab1SKenneth D. Merry 			 * will be removed.
1111*ef270ab1SKenneth D. Merry 			 */
1112*ef270ab1SKenneth D. Merry 			ocs_sm_transition(&domain->drvsm, __ocs_domain_init, NULL);
1113*ef270ab1SKenneth D. Merry 			ocs_sm_post_event(&domain->drvsm, OCS_EVT_DOMAIN_FOUND, &drec);
1114*ef270ab1SKenneth D. Merry 		} else {
1115*ef270ab1SKenneth D. Merry 			domain->req_domain_free = 1;
1116*ef270ab1SKenneth D. Merry 		}
1117*ef270ab1SKenneth D. Merry 		break;
1118*ef270ab1SKenneth D. Merry 	}
1119*ef270ab1SKenneth D. Merry 
1120*ef270ab1SKenneth D. Merry 	default:
1121*ef270ab1SKenneth D. Merry 		__ocs_domain_common_shutdown(__func__, ctx, evt, arg);
1122*ef270ab1SKenneth D. Merry 		return NULL;
1123*ef270ab1SKenneth D. Merry 	}
1124*ef270ab1SKenneth D. Merry 
1125*ef270ab1SKenneth D. Merry 	return NULL;
1126*ef270ab1SKenneth D. Merry }
1127*ef270ab1SKenneth D. Merry 
1128*ef270ab1SKenneth D. Merry /**
1129*ef270ab1SKenneth D. Merry  * @ingroup domain_sm
1130*ef270ab1SKenneth D. Merry  * @brief Domain state machine: Wait for the domain alloc/attach completion
1131*ef270ab1SKenneth D. Merry  * after receiving a domain lost.
1132*ef270ab1SKenneth D. Merry  *
1133*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1134*ef270ab1SKenneth D. Merry  * This state is entered when receiving a domain lost while waiting for a domain alloc
1135*ef270ab1SKenneth D. Merry  * or a domain attach to complete.
1136*ef270ab1SKenneth D. Merry  *
1137*ef270ab1SKenneth D. Merry  * @param ctx Remote node state machine context.
1138*ef270ab1SKenneth D. Merry  * @param evt Event to process.
1139*ef270ab1SKenneth D. Merry  * @param arg Per event optional argument.
1140*ef270ab1SKenneth D. Merry  *
1141*ef270ab1SKenneth D. Merry  * @return Returns NULL.
1142*ef270ab1SKenneth D. Merry  */
1143*ef270ab1SKenneth D. Merry 
1144*ef270ab1SKenneth D. Merry void *
__ocs_domain_wait_domain_lost(ocs_sm_ctx_t * ctx,ocs_sm_event_t evt,void * arg)1145*ef270ab1SKenneth D. Merry __ocs_domain_wait_domain_lost(ocs_sm_ctx_t *ctx, ocs_sm_event_t evt, void *arg)
1146*ef270ab1SKenneth D. Merry {
1147*ef270ab1SKenneth D. Merry 	std_domain_state_decl();
1148*ef270ab1SKenneth D. Merry 
1149*ef270ab1SKenneth D. Merry 	domain_sm_trace(domain);
1150*ef270ab1SKenneth D. Merry 
1151*ef270ab1SKenneth D. Merry 	switch(evt) {
1152*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ALLOC_OK:
1153*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ATTACH_OK: {
1154*ef270ab1SKenneth D. Merry 		int32_t rc;
1155*ef270ab1SKenneth D. Merry 		ocs_domain_lock(domain);
1156*ef270ab1SKenneth D. Merry 		if (!ocs_list_empty(&domain->sport_list)) {
1157*ef270ab1SKenneth D. Merry 			/* if there are sports, transition to wait state and send
1158*ef270ab1SKenneth D. Merry 			* shutdown to each sport */
1159*ef270ab1SKenneth D. Merry 			ocs_sport_t	*sport = NULL;
1160*ef270ab1SKenneth D. Merry 			ocs_sport_t	*sport_next = NULL;
1161*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_wait_sports_free, NULL);
1162*ef270ab1SKenneth D. Merry 			ocs_list_foreach_safe(&domain->sport_list, sport, sport_next) {
1163*ef270ab1SKenneth D. Merry 				ocs_sm_post_event(&sport->sm, OCS_EVT_SHUTDOWN, NULL);
1164*ef270ab1SKenneth D. Merry 			}
1165*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
1166*ef270ab1SKenneth D. Merry 		} else {
1167*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
1168*ef270ab1SKenneth D. Merry 			/* no sports exist, free domain */
1169*ef270ab1SKenneth D. Merry 			ocs_sm_transition(ctx, __ocs_domain_wait_shutdown, NULL);
1170*ef270ab1SKenneth D. Merry 			rc = ocs_hw_domain_free(&ocs->hw, domain);
1171*ef270ab1SKenneth D. Merry 			if (rc) {
1172*ef270ab1SKenneth D. Merry 				ocs_log_err(ocs, "ocs_hw_domain_free() failed: %d\n", rc);
1173*ef270ab1SKenneth D. Merry 				/* TODO: hw/device reset needed */
1174*ef270ab1SKenneth D. Merry 			}
1175*ef270ab1SKenneth D. Merry 		}
1176*ef270ab1SKenneth D. Merry 		break;
1177*ef270ab1SKenneth D. Merry 	}
1178*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ALLOC_FAIL:
1179*ef270ab1SKenneth D. Merry 	case OCS_EVT_DOMAIN_ATTACH_FAIL:
1180*ef270ab1SKenneth D. Merry 		ocs_log_err(ocs, "[domain] %-20s: failed\n", ocs_sm_event_name(evt));
1181*ef270ab1SKenneth D. Merry 		/* TODO: hw/device reset needed */
1182*ef270ab1SKenneth D. Merry 		break;
1183*ef270ab1SKenneth D. Merry 
1184*ef270ab1SKenneth D. Merry 	default:
1185*ef270ab1SKenneth D. Merry 		__ocs_domain_common_shutdown(__func__, ctx, evt, arg);
1186*ef270ab1SKenneth D. Merry 		return NULL;
1187*ef270ab1SKenneth D. Merry 	}
1188*ef270ab1SKenneth D. Merry 
1189*ef270ab1SKenneth D. Merry 	return NULL;
1190*ef270ab1SKenneth D. Merry }
1191*ef270ab1SKenneth D. Merry 
1192*ef270ab1SKenneth D. Merry /**
1193*ef270ab1SKenneth D. Merry  * @brief Save the port's service parameters.
1194*ef270ab1SKenneth D. Merry  *
1195*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1196*ef270ab1SKenneth D. Merry  * Service parameters from the fabric FLOGI are saved in the domain's
1197*ef270ab1SKenneth D. Merry  * flogi_service_params array.
1198*ef270ab1SKenneth D. Merry  *
1199*ef270ab1SKenneth D. Merry  * @param domain Pointer to the domain.
1200*ef270ab1SKenneth D. Merry  * @param payload Service parameters to save.
1201*ef270ab1SKenneth D. Merry  *
1202*ef270ab1SKenneth D. Merry  * @return None.
1203*ef270ab1SKenneth D. Merry  */
1204*ef270ab1SKenneth D. Merry 
1205*ef270ab1SKenneth D. Merry void
ocs_domain_save_sparms(ocs_domain_t * domain,void * payload)1206*ef270ab1SKenneth D. Merry ocs_domain_save_sparms(ocs_domain_t *domain, void *payload)
1207*ef270ab1SKenneth D. Merry {
1208*ef270ab1SKenneth D. Merry 	ocs_memcpy(domain->flogi_service_params, payload, sizeof (fc_plogi_payload_t));
1209*ef270ab1SKenneth D. Merry }
1210*ef270ab1SKenneth D. Merry /**
1211*ef270ab1SKenneth D. Merry  * @brief Initiator domain attach. (internal call only)
1212*ef270ab1SKenneth D. Merry  *
1213*ef270ab1SKenneth D. Merry  * Assumes that the domain SM lock is already locked
1214*ef270ab1SKenneth D. Merry  *
1215*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1216*ef270ab1SKenneth D. Merry  * The HW domain attach function is started.
1217*ef270ab1SKenneth D. Merry  *
1218*ef270ab1SKenneth D. Merry  * @param domain Pointer to the domain object.
1219*ef270ab1SKenneth D. Merry  * @param s_id FC_ID of which to register this domain.
1220*ef270ab1SKenneth D. Merry  *
1221*ef270ab1SKenneth D. Merry  * @return None.
1222*ef270ab1SKenneth D. Merry  */
1223*ef270ab1SKenneth D. Merry 
1224*ef270ab1SKenneth D. Merry void
__ocs_domain_attach_internal(ocs_domain_t * domain,uint32_t s_id)1225*ef270ab1SKenneth D. Merry __ocs_domain_attach_internal(ocs_domain_t *domain, uint32_t s_id)
1226*ef270ab1SKenneth D. Merry {
1227*ef270ab1SKenneth D. Merry 	ocs_memcpy(domain->dma.virt, ((uint8_t*)domain->flogi_service_params)+4, sizeof (fc_plogi_payload_t) - 4);
1228*ef270ab1SKenneth D. Merry 	(void)ocs_sm_post_event(&domain->drvsm, OCS_EVT_DOMAIN_REQ_ATTACH, &s_id);
1229*ef270ab1SKenneth D. Merry }
1230*ef270ab1SKenneth D. Merry 
1231*ef270ab1SKenneth D. Merry /**
1232*ef270ab1SKenneth D. Merry  * @brief Initiator domain attach.
1233*ef270ab1SKenneth D. Merry  *
1234*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1235*ef270ab1SKenneth D. Merry  * The HW domain attach function is started.
1236*ef270ab1SKenneth D. Merry  *
1237*ef270ab1SKenneth D. Merry  * @param domain Pointer to the domain object.
1238*ef270ab1SKenneth D. Merry  * @param s_id FC_ID of which to register this domain.
1239*ef270ab1SKenneth D. Merry  *
1240*ef270ab1SKenneth D. Merry  * @return None.
1241*ef270ab1SKenneth D. Merry  */
1242*ef270ab1SKenneth D. Merry 
1243*ef270ab1SKenneth D. Merry void
ocs_domain_attach(ocs_domain_t * domain,uint32_t s_id)1244*ef270ab1SKenneth D. Merry ocs_domain_attach(ocs_domain_t *domain, uint32_t s_id)
1245*ef270ab1SKenneth D. Merry {
1246*ef270ab1SKenneth D. Merry 	__ocs_domain_attach_internal(domain, s_id);
1247*ef270ab1SKenneth D. Merry }
1248*ef270ab1SKenneth D. Merry 
1249*ef270ab1SKenneth D. Merry int
ocs_domain_post_event(ocs_domain_t * domain,ocs_sm_event_t event,void * arg)1250*ef270ab1SKenneth D. Merry ocs_domain_post_event(ocs_domain_t *domain, ocs_sm_event_t event, void *arg)
1251*ef270ab1SKenneth D. Merry {
1252*ef270ab1SKenneth D. Merry 	int rc;
1253*ef270ab1SKenneth D. Merry 	int accept_frames;
1254*ef270ab1SKenneth D. Merry 	int req_domain_free;
1255*ef270ab1SKenneth D. Merry 
1256*ef270ab1SKenneth D. Merry 	rc = ocs_sm_post_event(&domain->drvsm, event, arg);
1257*ef270ab1SKenneth D. Merry 
1258*ef270ab1SKenneth D. Merry 	req_domain_free = domain->req_domain_free;
1259*ef270ab1SKenneth D. Merry 	domain->req_domain_free = 0;
1260*ef270ab1SKenneth D. Merry 
1261*ef270ab1SKenneth D. Merry 	accept_frames = domain->req_accept_frames;
1262*ef270ab1SKenneth D. Merry 	domain->req_accept_frames = 0;
1263*ef270ab1SKenneth D. Merry 
1264*ef270ab1SKenneth D. Merry 	if (accept_frames) {
1265*ef270ab1SKenneth D. Merry 		ocs_domain_accept_frames(domain);
1266*ef270ab1SKenneth D. Merry 	}
1267*ef270ab1SKenneth D. Merry 
1268*ef270ab1SKenneth D. Merry 	if (req_domain_free) {
1269*ef270ab1SKenneth D. Merry 		ocs_domain_free(domain);
1270*ef270ab1SKenneth D. Merry 	}
1271*ef270ab1SKenneth D. Merry 
1272*ef270ab1SKenneth D. Merry 	return rc;
1273*ef270ab1SKenneth D. Merry }
1274*ef270ab1SKenneth D. Merry 
1275*ef270ab1SKenneth D. Merry /**
1276*ef270ab1SKenneth D. Merry  * @brief Return the WWN as a uint64_t.
1277*ef270ab1SKenneth D. Merry  *
1278*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1279*ef270ab1SKenneth D. Merry  * Calls the HW property function for the WWNN or WWPN, and returns the value
1280*ef270ab1SKenneth D. Merry  * as a uint64_t.
1281*ef270ab1SKenneth D. Merry  *
1282*ef270ab1SKenneth D. Merry  * @param hw Pointer to the HW object.
1283*ef270ab1SKenneth D. Merry  * @param prop HW property.
1284*ef270ab1SKenneth D. Merry  *
1285*ef270ab1SKenneth D. Merry  * @return Returns uint64_t request value.
1286*ef270ab1SKenneth D. Merry  */
1287*ef270ab1SKenneth D. Merry 
1288*ef270ab1SKenneth D. Merry uint64_t
ocs_get_wwn(ocs_hw_t * hw,ocs_hw_property_e prop)1289*ef270ab1SKenneth D. Merry ocs_get_wwn(ocs_hw_t *hw, ocs_hw_property_e prop)
1290*ef270ab1SKenneth D. Merry {
1291*ef270ab1SKenneth D. Merry 	uint8_t *p = ocs_hw_get_ptr(hw, prop);
1292*ef270ab1SKenneth D. Merry 	uint64_t value = 0;
1293*ef270ab1SKenneth D. Merry 
1294*ef270ab1SKenneth D. Merry 	if (p) {
1295*ef270ab1SKenneth D. Merry 		uint32_t i;
1296*ef270ab1SKenneth D. Merry 		for (i = 0; i < sizeof(value); i++) {
1297*ef270ab1SKenneth D. Merry 			value = (value << 8) | p[i];
1298*ef270ab1SKenneth D. Merry 		}
1299*ef270ab1SKenneth D. Merry 	}
1300*ef270ab1SKenneth D. Merry 	return value;
1301*ef270ab1SKenneth D. Merry }
1302*ef270ab1SKenneth D. Merry 
1303*ef270ab1SKenneth D. Merry /**
1304*ef270ab1SKenneth D. Merry  * @brief Generate a domain ddump.
1305*ef270ab1SKenneth D. Merry  *
1306*ef270ab1SKenneth D. Merry  * <h3 class="desc">Description</h3>
1307*ef270ab1SKenneth D. Merry  * Generates a domain ddump.
1308*ef270ab1SKenneth D. Merry  *
1309*ef270ab1SKenneth D. Merry  * @param textbuf Pointer to the text buffer.
1310*ef270ab1SKenneth D. Merry  * @param domain Pointer to the domain context.
1311*ef270ab1SKenneth D. Merry  *
1312*ef270ab1SKenneth D. Merry  * @return Returns 0 on success, or a negative value on failure.
1313*ef270ab1SKenneth D. Merry  */
1314*ef270ab1SKenneth D. Merry 
1315*ef270ab1SKenneth D. Merry int
ocs_ddump_domain(ocs_textbuf_t * textbuf,ocs_domain_t * domain)1316*ef270ab1SKenneth D. Merry ocs_ddump_domain(ocs_textbuf_t *textbuf, ocs_domain_t *domain)
1317*ef270ab1SKenneth D. Merry {
1318*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
1319*ef270ab1SKenneth D. Merry 	int retval = 0;
1320*ef270ab1SKenneth D. Merry 
1321*ef270ab1SKenneth D. Merry 	ocs_ddump_section(textbuf, "domain", domain->instance_index);
1322*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "display_name", "%s", domain->display_name);
1323*ef270ab1SKenneth D. Merry 
1324*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "fcf", "%#x", domain->fcf);
1325*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "fcf_indicator", "%#x", domain->fcf_indicator);
1326*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "vlan_id", "%#x", domain->vlan_id);
1327*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "indicator", "%#x", domain->indicator);
1328*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "attached", "%d", domain->attached);
1329*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "is_loop", "%d", domain->is_loop);
1330*ef270ab1SKenneth D. Merry 	ocs_ddump_value(textbuf, "is_nlport", "%d", domain->is_nlport);
1331*ef270ab1SKenneth D. Merry 
1332*ef270ab1SKenneth D. Merry 	ocs_scsi_ini_ddump(textbuf, OCS_SCSI_DDUMP_DOMAIN, domain);
1333*ef270ab1SKenneth D. Merry 	ocs_scsi_tgt_ddump(textbuf, OCS_SCSI_DDUMP_DOMAIN, domain);
1334*ef270ab1SKenneth D. Merry 
1335*ef270ab1SKenneth D. Merry 	ocs_display_sparams(NULL, "domain_sparms", 1, textbuf, domain->dma.virt);
1336*ef270ab1SKenneth D. Merry 
1337*ef270ab1SKenneth D. Merry 	if (ocs_domain_lock_try(domain) != TRUE) {
1338*ef270ab1SKenneth D. Merry 		/* Didn't get the lock */
1339*ef270ab1SKenneth D. Merry 		return -1;
1340*ef270ab1SKenneth D. Merry 	}
1341*ef270ab1SKenneth D. Merry 		ocs_list_foreach(&domain->sport_list, sport) {
1342*ef270ab1SKenneth D. Merry 			retval = ocs_ddump_sport(textbuf, sport);
1343*ef270ab1SKenneth D. Merry 			if (retval != 0) {
1344*ef270ab1SKenneth D. Merry 				break;
1345*ef270ab1SKenneth D. Merry 			}
1346*ef270ab1SKenneth D. Merry 		}
1347*ef270ab1SKenneth D. Merry 
1348*ef270ab1SKenneth D. Merry #if defined(ENABLE_FABRIC_EMULATION)
1349*ef270ab1SKenneth D. Merry 		ocs_ddump_ns(textbuf, domain->ocs_ns);
1350*ef270ab1SKenneth D. Merry #endif
1351*ef270ab1SKenneth D. Merry 
1352*ef270ab1SKenneth D. Merry 	ocs_domain_unlock(domain);
1353*ef270ab1SKenneth D. Merry 
1354*ef270ab1SKenneth D. Merry 	ocs_ddump_endsection(textbuf, "domain", domain->instance_index);
1355*ef270ab1SKenneth D. Merry 
1356*ef270ab1SKenneth D. Merry 	return retval;
1357*ef270ab1SKenneth D. Merry }
1358*ef270ab1SKenneth D. Merry 
1359*ef270ab1SKenneth D. Merry void
ocs_mgmt_domain_list(ocs_textbuf_t * textbuf,void * object)1360*ef270ab1SKenneth D. Merry ocs_mgmt_domain_list(ocs_textbuf_t *textbuf, void *object)
1361*ef270ab1SKenneth D. Merry {
1362*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
1363*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = (ocs_domain_t *)object;
1364*ef270ab1SKenneth D. Merry 
1365*ef270ab1SKenneth D. Merry 	ocs_mgmt_start_section(textbuf, "domain", domain->instance_index);
1366*ef270ab1SKenneth D. Merry 
1367*ef270ab1SKenneth D. Merry 	/* Add my status values to textbuf */
1368*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "fcf");
1369*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "fcf_indicator");
1370*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "vlan_id");
1371*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "indicator");
1372*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "attached");
1373*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "is_loop");
1374*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "display_name");
1375*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_sports");
1376*ef270ab1SKenneth D. Merry #if defined(ENABLE_FABRIC_EMULATION)
1377*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RW, "femul_enable");
1378*ef270ab1SKenneth D. Merry #endif
1379*ef270ab1SKenneth D. Merry 
1380*ef270ab1SKenneth D. Merry 	if (ocs_domain_lock_try(domain) == TRUE) {
1381*ef270ab1SKenneth D. Merry 		/* If we get here, then we are holding the domain lock */
1382*ef270ab1SKenneth D. Merry 		ocs_list_foreach(&domain->sport_list, sport) {
1383*ef270ab1SKenneth D. Merry 			if ((sport->mgmt_functions) && (sport->mgmt_functions->get_list_handler)) {
1384*ef270ab1SKenneth D. Merry 				sport->mgmt_functions->get_list_handler(textbuf, sport);
1385*ef270ab1SKenneth D. Merry 			}
1386*ef270ab1SKenneth D. Merry 		}
1387*ef270ab1SKenneth D. Merry 		ocs_domain_unlock(domain);
1388*ef270ab1SKenneth D. Merry 	}
1389*ef270ab1SKenneth D. Merry 
1390*ef270ab1SKenneth D. Merry 	ocs_mgmt_end_section(textbuf, "domain", domain->instance_index);
1391*ef270ab1SKenneth D. Merry }
1392*ef270ab1SKenneth D. Merry 
1393*ef270ab1SKenneth D. Merry int
ocs_mgmt_domain_get(ocs_textbuf_t * textbuf,char * parent,char * name,void * object)1394*ef270ab1SKenneth D. Merry ocs_mgmt_domain_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
1395*ef270ab1SKenneth D. Merry {
1396*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
1397*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = (ocs_domain_t *)object;
1398*ef270ab1SKenneth D. Merry 	char qualifier[80];
1399*ef270ab1SKenneth D. Merry 	int retval = -1;
1400*ef270ab1SKenneth D. Merry 
1401*ef270ab1SKenneth D. Merry 	ocs_mgmt_start_section(textbuf, "domain", domain->instance_index);
1402*ef270ab1SKenneth D. Merry 
1403*ef270ab1SKenneth D. Merry 	snprintf(qualifier, sizeof(qualifier), "%s/domain[%d]", parent, domain->instance_index);
1404*ef270ab1SKenneth D. Merry 
1405*ef270ab1SKenneth D. Merry 	/* If it doesn't start with my qualifier I don't know what to do with it */
1406*ef270ab1SKenneth D. Merry 	if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1407*ef270ab1SKenneth D. Merry 		char *unqualified_name = name + strlen(qualifier) +1;
1408*ef270ab1SKenneth D. Merry 
1409*ef270ab1SKenneth D. Merry 		/* See if it's a value I can supply */
1410*ef270ab1SKenneth D. Merry 		if (ocs_strcmp(unqualified_name, "display_name") == 0) {
1411*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", domain->display_name);
1412*ef270ab1SKenneth D. Merry 			retval = 0;
1413*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "fcf") == 0) {
1414*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fcf", "%#x", domain->fcf);
1415*ef270ab1SKenneth D. Merry 			retval = 0;
1416*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "fcf_indicator") == 0) {
1417*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fcf_indicator", "%#x", domain->fcf_indicator);
1418*ef270ab1SKenneth D. Merry 			retval = 0;
1419*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "vlan_id") == 0) {
1420*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "vlan_id", "%#x", domain->vlan_id);
1421*ef270ab1SKenneth D. Merry 			retval = 0;
1422*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "indicator") == 0) {
1423*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "indicator", "%#x", domain->indicator);
1424*ef270ab1SKenneth D. Merry 			retval = 0;
1425*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "attached") == 0) {
1426*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "attached", domain->attached);
1427*ef270ab1SKenneth D. Merry 			retval = 0;
1428*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "is_loop") == 0) {
1429*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "is_loop",  domain->is_loop);
1430*ef270ab1SKenneth D. Merry 			retval = 0;
1431*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "is_nlport") == 0) {
1432*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "is_nlport",  domain->is_nlport);
1433*ef270ab1SKenneth D. Merry 			retval = 0;
1434*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "display_name") == 0) {
1435*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", domain->display_name);
1436*ef270ab1SKenneth D. Merry 			retval = 0;
1437*ef270ab1SKenneth D. Merry #if defined(ENABLE_FABRIC_EMULATION)
1438*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "femul_enable") == 0) {
1439*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "femul_enable", "%d", domain->femul_enable);
1440*ef270ab1SKenneth D. Merry 			retval = 0;
1441*ef270ab1SKenneth D. Merry #endif
1442*ef270ab1SKenneth D. Merry 		} else if (ocs_strcmp(unqualified_name, "num_sports") == 0) {
1443*ef270ab1SKenneth D. Merry 			ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_sports", "%d", domain->sport_instance_count);
1444*ef270ab1SKenneth D. Merry 			retval = 0;
1445*ef270ab1SKenneth D. Merry 		} else {
1446*ef270ab1SKenneth D. Merry 			/* If I didn't know the value of this status pass the request to each of my children */
1447*ef270ab1SKenneth D. Merry 
1448*ef270ab1SKenneth D. Merry 			ocs_domain_lock(domain);
1449*ef270ab1SKenneth D. Merry 			ocs_list_foreach(&domain->sport_list, sport) {
1450*ef270ab1SKenneth D. Merry 				if ((sport->mgmt_functions) && (sport->mgmt_functions->get_handler)) {
1451*ef270ab1SKenneth D. Merry 					retval = sport->mgmt_functions->get_handler(textbuf, qualifier, name, sport);
1452*ef270ab1SKenneth D. Merry 				}
1453*ef270ab1SKenneth D. Merry 
1454*ef270ab1SKenneth D. Merry 				if (retval == 0) {
1455*ef270ab1SKenneth D. Merry 					break;
1456*ef270ab1SKenneth D. Merry 				}
1457*ef270ab1SKenneth D. Merry 			}
1458*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
1459*ef270ab1SKenneth D. Merry 		}
1460*ef270ab1SKenneth D. Merry 	}
1461*ef270ab1SKenneth D. Merry 
1462*ef270ab1SKenneth D. Merry 	ocs_mgmt_end_section(textbuf, "domain", domain->instance_index);
1463*ef270ab1SKenneth D. Merry 	return retval;
1464*ef270ab1SKenneth D. Merry }
1465*ef270ab1SKenneth D. Merry 
1466*ef270ab1SKenneth D. Merry void
ocs_mgmt_domain_get_all(ocs_textbuf_t * textbuf,void * object)1467*ef270ab1SKenneth D. Merry ocs_mgmt_domain_get_all(ocs_textbuf_t *textbuf, void *object)
1468*ef270ab1SKenneth D. Merry {
1469*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
1470*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = (ocs_domain_t *)object;
1471*ef270ab1SKenneth D. Merry 
1472*ef270ab1SKenneth D. Merry 	ocs_mgmt_start_section(textbuf, "domain", domain->instance_index);
1473*ef270ab1SKenneth D. Merry 
1474*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "display_name", domain->display_name);
1475*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fcf", "%#x", domain->fcf);
1476*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fcf_indicator", "%#x", domain->fcf_indicator);
1477*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "vlan_id", "%#x", domain->vlan_id);
1478*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "indicator", "%#x", domain->indicator);
1479*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "attached", domain->attached);
1480*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "is_loop",  domain->is_loop);
1481*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "is_nlport",  domain->is_nlport);
1482*ef270ab1SKenneth D. Merry #if defined(ENABLE_FABRIC_EMULATION)
1483*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "femul_enable", "%d", domain->femul_enable);
1484*ef270ab1SKenneth D. Merry #endif
1485*ef270ab1SKenneth D. Merry 	ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_sports",  "%d", domain->sport_instance_count);
1486*ef270ab1SKenneth D. Merry 
1487*ef270ab1SKenneth D. Merry 	ocs_domain_lock(domain);
1488*ef270ab1SKenneth D. Merry 	ocs_list_foreach(&domain->sport_list, sport) {
1489*ef270ab1SKenneth D. Merry 		if ((sport->mgmt_functions) && (sport->mgmt_functions->get_all_handler)) {
1490*ef270ab1SKenneth D. Merry 			sport->mgmt_functions->get_all_handler(textbuf, sport);
1491*ef270ab1SKenneth D. Merry 		}
1492*ef270ab1SKenneth D. Merry 	}
1493*ef270ab1SKenneth D. Merry 	ocs_domain_unlock(domain);
1494*ef270ab1SKenneth D. Merry 
1495*ef270ab1SKenneth D. Merry 	ocs_mgmt_end_unnumbered_section(textbuf, "domain");
1496*ef270ab1SKenneth D. Merry 
1497*ef270ab1SKenneth D. Merry }
1498*ef270ab1SKenneth D. Merry 
1499*ef270ab1SKenneth D. Merry int
ocs_mgmt_domain_set(char * parent,char * name,char * value,void * object)1500*ef270ab1SKenneth D. Merry ocs_mgmt_domain_set(char *parent, char *name, char *value, void *object)
1501*ef270ab1SKenneth D. Merry {
1502*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
1503*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = (ocs_domain_t *)object;
1504*ef270ab1SKenneth D. Merry 	char qualifier[80];
1505*ef270ab1SKenneth D. Merry 	int retval = -1;
1506*ef270ab1SKenneth D. Merry 
1507*ef270ab1SKenneth D. Merry 	snprintf(qualifier, sizeof(qualifier), "%s/domain[%d]", parent, domain->instance_index);
1508*ef270ab1SKenneth D. Merry 
1509*ef270ab1SKenneth D. Merry 	/* If it doesn't start with my qualifier I don't know what to do with it */
1510*ef270ab1SKenneth D. Merry 	if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
1511*ef270ab1SKenneth D. Merry 		/* See if it's a value I can supply */
1512*ef270ab1SKenneth D. Merry 
1513*ef270ab1SKenneth D. Merry 		/* if (ocs_strcmp(unqualified_name, "display_name") == 0) {
1514*ef270ab1SKenneth D. Merry 		} else */
1515*ef270ab1SKenneth D. Merry 		{
1516*ef270ab1SKenneth D. Merry 			/* If I didn't know the value of this status pass the request to each of my children */
1517*ef270ab1SKenneth D. Merry 			ocs_domain_lock(domain);
1518*ef270ab1SKenneth D. Merry 			ocs_list_foreach(&domain->sport_list, sport) {
1519*ef270ab1SKenneth D. Merry 				if ((sport->mgmt_functions) && (sport->mgmt_functions->set_handler)) {
1520*ef270ab1SKenneth D. Merry 					retval = sport->mgmt_functions->set_handler(qualifier, name, value, sport);
1521*ef270ab1SKenneth D. Merry 				}
1522*ef270ab1SKenneth D. Merry 
1523*ef270ab1SKenneth D. Merry 				if (retval == 0) {
1524*ef270ab1SKenneth D. Merry 					break;
1525*ef270ab1SKenneth D. Merry 				}
1526*ef270ab1SKenneth D. Merry 			}
1527*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
1528*ef270ab1SKenneth D. Merry 		}
1529*ef270ab1SKenneth D. Merry 	}
1530*ef270ab1SKenneth D. Merry 
1531*ef270ab1SKenneth D. Merry 	return retval;
1532*ef270ab1SKenneth D. Merry }
1533*ef270ab1SKenneth D. Merry 
1534*ef270ab1SKenneth D. Merry int
ocs_mgmt_domain_exec(char * parent,char * action,void * arg_in,uint32_t arg_in_length,void * arg_out,uint32_t arg_out_length,void * object)1535*ef270ab1SKenneth D. Merry ocs_mgmt_domain_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
1536*ef270ab1SKenneth D. Merry 			void *arg_out, uint32_t arg_out_length, void *object)
1537*ef270ab1SKenneth D. Merry {
1538*ef270ab1SKenneth D. Merry 	ocs_sport_t *sport;
1539*ef270ab1SKenneth D. Merry 	ocs_domain_t *domain = (ocs_domain_t *)object;
1540*ef270ab1SKenneth D. Merry 	char qualifier[80];
1541*ef270ab1SKenneth D. Merry 	int retval = -1;
1542*ef270ab1SKenneth D. Merry 
1543*ef270ab1SKenneth D. Merry 	snprintf(qualifier, sizeof(qualifier), "%s.domain%d", parent, domain->instance_index);
1544*ef270ab1SKenneth D. Merry 
1545*ef270ab1SKenneth D. Merry 	/* If it doesn't start with my qualifier I don't know what to do with it */
1546*ef270ab1SKenneth D. Merry 	if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
1547*ef270ab1SKenneth D. Merry 		{
1548*ef270ab1SKenneth D. Merry 			/* If I didn't know how to do this action pass the request to each of my children */
1549*ef270ab1SKenneth D. Merry 			ocs_domain_lock(domain);
1550*ef270ab1SKenneth D. Merry 			ocs_list_foreach(&domain->sport_list, sport) {
1551*ef270ab1SKenneth D. Merry 				if ((sport->mgmt_functions) && (sport->mgmt_functions->exec_handler)) {
1552*ef270ab1SKenneth D. Merry 					retval = sport->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length, arg_out, arg_out_length, sport);
1553*ef270ab1SKenneth D. Merry 				}
1554*ef270ab1SKenneth D. Merry 
1555*ef270ab1SKenneth D. Merry 				if (retval == 0) {
1556*ef270ab1SKenneth D. Merry 					break;
1557*ef270ab1SKenneth D. Merry 				}
1558*ef270ab1SKenneth D. Merry 			}
1559*ef270ab1SKenneth D. Merry 			ocs_domain_unlock(domain);
1560*ef270ab1SKenneth D. Merry 		}
1561*ef270ab1SKenneth D. Merry 	}
1562*ef270ab1SKenneth D. Merry 
1563*ef270ab1SKenneth D. Merry 	return retval;
1564*ef270ab1SKenneth D. Merry }
1565