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