1331766Sken/*- 2331766Sken * Copyright (c) 2017 Broadcom. All rights reserved. 3331766Sken * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 4331766Sken * 5331766Sken * Redistribution and use in source and binary forms, with or without 6331766Sken * modification, are permitted provided that the following conditions are met: 7331766Sken * 8331766Sken * 1. Redistributions of source code must retain the above copyright notice, 9331766Sken * this list of conditions and the following disclaimer. 10331766Sken * 11331766Sken * 2. Redistributions in binary form must reproduce the above copyright notice, 12331766Sken * this list of conditions and the following disclaimer in the documentation 13331766Sken * and/or other materials provided with the distribution. 14331766Sken * 15331766Sken * 3. Neither the name of the copyright holder nor the names of its contributors 16331766Sken * may be used to endorse or promote products derived from this software 17331766Sken * without specific prior written permission. 18331766Sken * 19331766Sken * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20331766Sken * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21331766Sken * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22331766Sken * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23331766Sken * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24331766Sken * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25331766Sken * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26331766Sken * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27331766Sken * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28331766Sken * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29331766Sken * POSSIBILITY OF SUCH DAMAGE. 30331766Sken * 31331766Sken * $FreeBSD: stable/11/sys/dev/ocs_fc/ocs_mgmt.c 343371 2019-01-24 01:04:23Z markj $ 32331766Sken */ 33331766Sken 34331766Sken/** 35331766Sken * @file 36331766Sken * The ocs_mgmt top level functions for Fibre Channel. 37331766Sken */ 38331766Sken 39331766Sken/** 40331766Sken * @defgroup mgmt Management Functions 41331766Sken */ 42331766Sken 43331766Sken#include "ocs.h" 44331766Sken#include "ocs_mgmt.h" 45331766Sken#include "ocs_vpd.h" 46331766Sken 47331766Sken#define SFP_PAGE_SIZE 128 48331766Sken 49331766Sken/* Executables*/ 50331766Sken 51331766Skenstatic int ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t); 52331766Skenstatic int ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t); 53331766Skenstatic int ocs_mgmt_function_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t); 54331766Sken 55331766Skenstatic void ocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg); 56331766Skenstatic int ocs_mgmt_force_assert(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t); 57331766Sken 58331766Sken#if defined(OCS_INCLUDE_RAMD) 59331766Skenstatic int32_t 60331766Skenocs_mgmt_read_phys(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t); 61331766Sken#endif 62331766Sken 63331766Sken 64331766Sken/* Getters */ 65331766Sken 66331766Skenstatic void get_nodes_count(ocs_t *, char *, ocs_textbuf_t*); 67331766Skenstatic void get_desc(ocs_t *, char *, ocs_textbuf_t*); 68331766Skenstatic void get_fw_rev(ocs_t *, char *, ocs_textbuf_t*); 69331766Skenstatic void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t*); 70331766Skenstatic void get_ipl(ocs_t *, char *, ocs_textbuf_t*); 71331766Skenstatic void get_wwnn(ocs_t *, char *, ocs_textbuf_t*); 72331766Skenstatic void get_wwpn(ocs_t *, char *, ocs_textbuf_t*); 73331766Skenstatic void get_fcid(ocs_t *, char *, ocs_textbuf_t *); 74331766Skenstatic void get_sn(ocs_t *, char *, ocs_textbuf_t*); 75331766Skenstatic void get_pn(ocs_t *, char *, ocs_textbuf_t*); 76331766Skenstatic void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t*); 77331766Skenstatic void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t*); 78331766Skenstatic void get_asic_id(ocs_t *, char *, ocs_textbuf_t*); 79331766Skenstatic void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t*); 80331766Skenstatic void get_pci_device(ocs_t *, char *, ocs_textbuf_t*); 81331766Skenstatic void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t*); 82331766Skenstatic void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t*); 83331766Skenstatic void get_businfo(ocs_t *, char *, ocs_textbuf_t*); 84331766Skenstatic void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t*); 85331766Skenstatic void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t*); 86331766Skenstatic void get_hw_rev1(ocs_t *, char *, ocs_textbuf_t*); 87331766Skenstatic void get_hw_rev2(ocs_t *, char *, ocs_textbuf_t*); 88331766Skenstatic void get_hw_rev3(ocs_t *, char *, ocs_textbuf_t*); 89331766Skenstatic void get_debug_mq_dump(ocs_t*, char*, ocs_textbuf_t*); 90331766Skenstatic void get_debug_cq_dump(ocs_t*, char*, ocs_textbuf_t*); 91331766Skenstatic void get_debug_wq_dump(ocs_t*, char*, ocs_textbuf_t*); 92331766Skenstatic void get_debug_eq_dump(ocs_t*, char*, ocs_textbuf_t*); 93331766Skenstatic void get_logmask(ocs_t*, char*, ocs_textbuf_t*); 94331766Skenstatic void get_current_speed(ocs_t*, char*, ocs_textbuf_t*); 95331766Skenstatic void get_current_topology(ocs_t*, char*, ocs_textbuf_t*); 96331766Skenstatic void get_current_link_state(ocs_t*, char*, ocs_textbuf_t*); 97331766Skenstatic void get_configured_speed(ocs_t*, char*, ocs_textbuf_t*); 98331766Skenstatic void get_configured_topology(ocs_t*, char*, ocs_textbuf_t*); 99331766Skenstatic void get_configured_link_state(ocs_t*, char*, ocs_textbuf_t*); 100331766Skenstatic void get_linkcfg(ocs_t*, char*, ocs_textbuf_t*); 101331766Skenstatic void get_req_wwnn(ocs_t*, char*, ocs_textbuf_t*); 102331766Skenstatic void get_req_wwpn(ocs_t*, char*, ocs_textbuf_t*); 103331766Skenstatic void get_nodedb_mask(ocs_t*, char*, ocs_textbuf_t*); 104331766Skenstatic void get_profile_list(ocs_t*, char*, ocs_textbuf_t*); 105331766Skenstatic void get_active_profile(ocs_t*, char*, ocs_textbuf_t*); 106331766Skenstatic void get_port_protocol(ocs_t*, char*, ocs_textbuf_t*); 107331766Skenstatic void get_driver_version(ocs_t*, char*, ocs_textbuf_t*); 108331766Skenstatic void get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 109331766Skenstatic void get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 110331766Skenstatic void get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 111331766Skenstatic void get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 112331766Skenstatic void get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 113331766Skenstatic void get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 114331766Skenstatic void get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 115331766Skenstatic void get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 116331766Skenstatic void get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 117331766Skenstatic void get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 118331766Skenstatic void get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 119331766Skenstatic void get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 120331766Skenstatic void get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf); 121331766Sken 122331766Sken/* Setters */ 123331766Skenstatic int set_debug_mq_dump(ocs_t*, char*, char*); 124331766Skenstatic int set_debug_cq_dump(ocs_t*, char*, char*); 125331766Skenstatic int set_debug_wq_dump(ocs_t*, char*, char*); 126331766Skenstatic int set_debug_eq_dump(ocs_t*, char*, char*); 127331766Skenstatic int set_logmask(ocs_t*, char*, char*); 128331766Skenstatic int set_configured_link_state(ocs_t*, char*, char*); 129331766Skenstatic int set_linkcfg(ocs_t*, char*, char*); 130331766Skenstatic int set_nodedb_mask(ocs_t*, char*, char*); 131331766Skenstatic int set_port_protocol(ocs_t*, char*, char*); 132331766Skenstatic int set_active_profile(ocs_t*, char*, char*); 133331766Skenstatic int set_tgt_rscn_delay(ocs_t*, char*, char*); 134331766Skenstatic int set_tgt_rscn_period(ocs_t*, char*, char*); 135331766Skenstatic int set_inject_drop_cmd(ocs_t*, char*, char*); 136331766Skenstatic int set_inject_free_drop_cmd(ocs_t*, char*, char*); 137331766Skenstatic int set_inject_drop_data(ocs_t*, char*, char*); 138331766Skenstatic int set_inject_drop_resp(ocs_t*, char*, char*); 139331766Skenstatic int set_cmd_err_inject(ocs_t*, char*, char*); 140331766Skenstatic int set_cmd_delay_value(ocs_t*, char*, char*); 141331766Skenstatic int set_nv_wwn(ocs_t*, char*, char*); 142331766Skenstatic int set_loglevel(ocs_t*, char*, char*); 143331766Sken 144331766Skenstatic void ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg); 145331766Sken#if defined(OCS_INCLUDE_RAMD) 146331766Skenstatic void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr); 147331766Sken#endif 148331766Sken 149331766Skenocs_mgmt_table_entry_t mgmt_table[] = { 150331766Sken {"nodes_count", get_nodes_count, NULL, NULL}, 151331766Sken {"desc", get_desc, NULL, NULL}, 152331766Sken {"fw_rev", get_fw_rev, NULL, NULL}, 153331766Sken {"fw_rev2", get_fw_rev2, NULL, NULL}, 154331766Sken {"ipl", get_ipl, NULL, NULL}, 155331766Sken {"hw_rev1", get_hw_rev1, NULL, NULL}, 156331766Sken {"hw_rev2", get_hw_rev2, NULL, NULL}, 157331766Sken {"hw_rev3", get_hw_rev3, NULL, NULL}, 158331766Sken {"wwnn", get_wwnn, NULL, NULL}, 159331766Sken {"wwpn", get_wwpn, NULL, NULL}, 160331766Sken {"fc_id", get_fcid, NULL, NULL}, 161331766Sken {"sn", get_sn, NULL, NULL}, 162331766Sken {"pn", get_pn, NULL, NULL}, 163331766Sken {"sli4_intf_reg", get_sli4_intf_reg, NULL, NULL}, 164331766Sken {"phy_port_num", get_phy_port_num, NULL, NULL}, 165331766Sken {"asic_id_reg", get_asic_id, NULL, NULL}, 166331766Sken {"pci_vendor", get_pci_vendor, NULL, NULL}, 167331766Sken {"pci_device", get_pci_device, NULL, NULL}, 168331766Sken {"pci_subsystem_vendor", get_pci_subsystem_vendor, NULL, NULL}, 169331766Sken {"pci_subsystem_device", get_pci_subsystem_device, NULL, NULL}, 170331766Sken {"businfo", get_businfo, NULL, NULL}, 171331766Sken {"sfp_a0", get_sfp_a0, NULL, NULL}, 172331766Sken {"sfp_a2", get_sfp_a2, NULL, NULL}, 173331766Sken {"profile_list", get_profile_list, NULL, NULL}, 174331766Sken {"driver_version", get_driver_version, NULL, NULL}, 175331766Sken {"current_speed", get_current_speed, NULL, NULL}, 176331766Sken {"current_topology", get_current_topology, NULL, NULL}, 177331766Sken {"current_link_state", get_current_link_state, NULL, NULL}, 178331766Sken {"chip_type", get_chip_type, NULL, NULL}, 179331766Sken {"configured_speed", get_configured_speed, set_configured_speed, NULL}, 180331766Sken {"configured_topology", get_configured_topology, set_configured_topology, NULL}, 181331766Sken {"configured_link_state", get_configured_link_state, set_configured_link_state, NULL}, 182331766Sken {"debug_mq_dump", get_debug_mq_dump, set_debug_mq_dump, NULL}, 183331766Sken {"debug_cq_dump", get_debug_cq_dump, set_debug_cq_dump, NULL}, 184331766Sken {"debug_wq_dump", get_debug_wq_dump, set_debug_wq_dump, NULL}, 185331766Sken {"debug_eq_dump", get_debug_eq_dump, set_debug_eq_dump, NULL}, 186331766Sken {"logmask", get_logmask, set_logmask, NULL}, 187331766Sken {"loglevel", get_loglevel, set_loglevel, NULL}, 188331766Sken {"linkcfg", get_linkcfg, set_linkcfg, NULL}, 189331766Sken {"requested_wwnn", get_req_wwnn, set_req_wwnn, NULL}, 190331766Sken {"requested_wwpn", get_req_wwpn, set_req_wwpn, NULL}, 191331766Sken {"nodedb_mask", get_nodedb_mask, set_nodedb_mask, NULL}, 192331766Sken {"port_protocol", get_port_protocol, set_port_protocol, NULL}, 193331766Sken {"active_profile", get_active_profile, set_active_profile, NULL}, 194331766Sken {"firmware_write", NULL, NULL, ocs_mgmt_firmware_write}, 195331766Sken {"firmware_reset", NULL, NULL, ocs_mgmt_firmware_reset}, 196331766Sken {"function_reset", NULL, NULL, ocs_mgmt_function_reset}, 197331766Sken#if defined(OCS_INCLUDE_RAMD) 198331766Sken {"read_phys", NULL, NULL, ocs_mgmt_read_phys}, 199331766Sken#endif 200331766Sken {"force_assert", NULL, NULL, ocs_mgmt_force_assert}, 201331766Sken 202331766Sken {"tgt_rscn_delay", get_tgt_rscn_delay, set_tgt_rscn_delay, NULL}, 203331766Sken {"tgt_rscn_period", get_tgt_rscn_period, set_tgt_rscn_period, NULL}, 204331766Sken {"inject_drop_cmd", get_inject_drop_cmd, set_inject_drop_cmd, NULL}, 205331766Sken {"inject_free_drop_cmd", get_inject_free_drop_cmd, set_inject_free_drop_cmd, NULL}, 206331766Sken {"inject_drop_data", get_inject_drop_data, set_inject_drop_data, NULL}, 207331766Sken {"inject_drop_resp", get_inject_drop_resp, set_inject_drop_resp, NULL}, 208331766Sken {"cmd_err_inject", get_cmd_err_inject, set_cmd_err_inject, NULL}, 209331766Sken {"cmd_delay_value", get_cmd_delay_value, set_cmd_delay_value, NULL}, 210331766Sken {"nv_wwpn", get_nv_wwpn, NULL, NULL}, 211331766Sken {"nv_wwnn", get_nv_wwnn, NULL, NULL}, 212331766Sken {"nv_wwn", NULL, set_nv_wwn, NULL}, 213331766Sken {"node_abort_cnt", get_node_abort_cnt, NULL, NULL}, 214331766Sken}; 215331766Sken 216331766Sken/** 217331766Sken * @ingroup mgmt 218331766Sken * @brief Get a list of options supported by the driver. 219331766Sken * 220331766Sken * @par Description 221331766Sken * This is the top level "get list" handler for the driver. It 222331766Sken * performs the following: 223331766Sken * - Adds entries to the textbuf for any actions supported by this level in the driver. 224331766Sken * - Calls a back-end function to add any actions supported by the back-end. 225331766Sken * - Calls a function on each child (domain) to recursively add supported actions. 226331766Sken * 227331766Sken * @param ocs Pointer to the ocs structure. 228331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to accumulate the results. 229331766Sken * 230331766Sken * @return Returns 0 on success, or a negative value on failure. 231331766Sken */ 232331766Sken 233331766Skenvoid 234331766Skenocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf) 235331766Sken{ 236331766Sken ocs_domain_t *domain; 237331766Sken uint32_t i; 238331766Sken int access; 239331766Sken 240331766Sken ocs_mgmt_start_unnumbered_section(textbuf, "ocs"); 241331766Sken 242331766Sken for (i=0;i<ARRAY_SIZE(mgmt_table);i++) { 243331766Sken access = 0; 244331766Sken if (mgmt_table[i].get_handler) { 245331766Sken access |= MGMT_MODE_RD; 246331766Sken } 247331766Sken if (mgmt_table[i].set_handler) { 248331766Sken access |= MGMT_MODE_WR; 249331766Sken } 250331766Sken if (mgmt_table[i].action_handler) { 251331766Sken access |= MGMT_MODE_EX; 252331766Sken } 253331766Sken ocs_mgmt_emit_property_name(textbuf, access, mgmt_table[i].name); 254331766Sken } 255331766Sken 256331766Sken if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_list_handler)) { 257331766Sken ocs->mgmt_functions->get_list_handler(textbuf, ocs); 258331766Sken } 259331766Sken 260331766Sken if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_list_handler)) { 261331766Sken ocs->tgt_mgmt_functions->get_list_handler(textbuf, &(ocs->tgt_ocs)); 262331766Sken } 263331766Sken 264331766Sken /* Have each of my children add their actions */ 265331766Sken if (ocs_device_lock_try(ocs) == TRUE) { 266331766Sken 267331766Sken /* If we get here then we are holding the device lock */ 268331766Sken ocs_list_foreach(&ocs->domain_list, domain) { 269331766Sken if ((domain->mgmt_functions) && (domain->mgmt_functions->get_list_handler)) { 270331766Sken domain->mgmt_functions->get_list_handler(textbuf, domain); 271331766Sken } 272331766Sken } 273331766Sken ocs_device_unlock(ocs); 274331766Sken } 275331766Sken 276331766Sken ocs_mgmt_end_unnumbered_section(textbuf, "ocs"); 277331766Sken 278331766Sken} 279331766Sken 280331766Sken/** 281331766Sken * @ingroup mgmt 282331766Sken * @brief Return the value of a management item. 283331766Sken * 284331766Sken * @par Description 285331766Sken * This is the top level "get" handler for the driver. It 286331766Sken * performs the following: 287331766Sken * - Checks that the qualifier portion of the name begins with my qualifier (ocs). 288331766Sken * - If the remaining part of the name matches a parameter that is known at this level, 289331766Sken * writes the value into textbuf. 290331766Sken * - If the name is not known, sends the request to the back-ends to fulfill (if possible). 291331766Sken * - If the request has not been fulfilled by the back-end, 292331766Sken * passes the request to each of the children (domains) to 293331766Sken * have them (recursively) try to respond. 294331766Sken * 295331766Sken * In passing the request to other entities, the request is considered to be answered 296331766Sken * when a response has been written into textbuf, indicated by textbuf->buffer_written 297331766Sken * being non-zero. 298331766Sken * 299331766Sken * @param ocs Pointer to the ocs structure. 300331766Sken * @param name Name of the status item to be retrieved. 301331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to return the results. 302331766Sken * 303331766Sken * @return Returns 0 if the value was found and returned, or -1 if an error occurred. 304331766Sken */ 305331766Sken 306331766Sken 307331766Skenint 308331766Skenocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 309331766Sken{ 310331766Sken ocs_domain_t *domain; 311331766Sken char qualifier[6]; 312331766Sken int retval = -1; 313331766Sken uint32_t i; 314331766Sken 315331766Sken ocs_mgmt_start_unnumbered_section(textbuf, "ocs"); 316331766Sken 317331766Sken 318331766Sken snprintf(qualifier, sizeof(qualifier), "/ocs"); 319331766Sken 320331766Sken /* See if the name starts with my qualifier. If not then this request isn't for me */ 321331766Sken if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) { 322331766Sken char *unqualified_name = name + strlen(qualifier) + 1; 323331766Sken 324331766Sken for (i=0;i<ARRAY_SIZE(mgmt_table);i++) { 325331766Sken if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) { 326331766Sken if (mgmt_table[i].get_handler) { 327331766Sken mgmt_table[i].get_handler(ocs, name, textbuf); 328331766Sken ocs_mgmt_end_unnumbered_section(textbuf, "ocs"); 329331766Sken return 0; 330331766Sken } 331331766Sken } 332331766Sken } 333331766Sken 334331766Sken if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_handler)) { 335331766Sken retval = ocs->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, ocs); 336331766Sken } 337331766Sken 338331766Sken if (retval != 0) { 339331766Sken if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_handler)) { 340331766Sken retval = ocs->tgt_mgmt_functions->get_handler(textbuf, qualifier, 341331766Sken (char*)name, &(ocs->tgt_ocs)); 342331766Sken } 343331766Sken } 344331766Sken 345331766Sken if (retval != 0) { 346331766Sken /* The driver didn't handle it, pass it to each domain */ 347331766Sken 348331766Sken ocs_device_lock(ocs); 349331766Sken ocs_list_foreach(&ocs->domain_list, domain) { 350331766Sken if ((domain->mgmt_functions) && (domain->mgmt_functions->get_handler)) { 351331766Sken retval = domain->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, domain); 352331766Sken } 353331766Sken 354331766Sken if (retval == 0) { 355331766Sken break; 356331766Sken } 357331766Sken 358331766Sken 359331766Sken } 360331766Sken ocs_device_unlock(ocs); 361331766Sken } 362331766Sken 363331766Sken } 364331766Sken 365331766Sken ocs_mgmt_end_unnumbered_section(textbuf, "ocs"); 366331766Sken 367331766Sken return retval; 368331766Sken} 369331766Sken 370331766Sken 371331766Sken/** 372331766Sken * @ingroup mgmt 373331766Sken * @brief Set the value of a mgmt item. 374331766Sken * 375331766Sken * @par Description 376331766Sken * This is the top level "set" handler for the driver. It 377331766Sken * performs the following: 378331766Sken * - Checks that the qualifier portion of the name begins with my qualifier (ocs). 379331766Sken * - If the remaining part of the name matches a parameter that is known at this level, 380331766Sken * calls the correct function to change the configuration. 381331766Sken * - If the name is not known, sends the request to the back-ends to fulfill (if possible). 382331766Sken * - If the request has not been fulfilled by the back-end, passes the request to each of the 383331766Sken * children (domains) to have them (recursively) try to respond. 384331766Sken * 385331766Sken * In passing the request to other entities, the request is considered to be handled 386331766Sken * if the function returns 0. 387331766Sken * 388331766Sken * @param ocs Pointer to the ocs structure. 389331766Sken * @param name Name of the property to be changed. 390331766Sken * @param value Requested new value of the property. 391331766Sken * 392331766Sken * @return Returns 0 if the configuration value was updated, or -1 otherwise. 393331766Sken */ 394331766Sken 395331766Skenint 396331766Skenocs_mgmt_set(ocs_t *ocs, char *name, char *value) 397331766Sken{ 398331766Sken ocs_domain_t *domain; 399331766Sken int result = -1; 400331766Sken char qualifier[80]; 401331766Sken uint32_t i; 402331766Sken 403331766Sken snprintf(qualifier, sizeof(qualifier), "/ocs"); 404331766Sken 405331766Sken /* If it doesn't start with my qualifier I don't know what to do with it */ 406331766Sken if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) { 407331766Sken char *unqualified_name = name + strlen(qualifier) +1; 408331766Sken 409331766Sken /* See if it's a value I can set */ 410331766Sken for (i=0;i<ARRAY_SIZE(mgmt_table);i++) { 411331766Sken if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) { 412331766Sken if (mgmt_table[i].set_handler) { 413331766Sken return mgmt_table[i].set_handler(ocs, name, value); 414331766Sken } 415331766Sken } 416331766Sken } 417331766Sken 418331766Sken if ((ocs->mgmt_functions) && (ocs->mgmt_functions->set_handler)) { 419331766Sken result = ocs->mgmt_functions->set_handler(qualifier, name, (char *)value, ocs); 420331766Sken } 421331766Sken 422331766Sken if (result != 0) { 423331766Sken if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->set_handler)) { 424331766Sken result = ocs->tgt_mgmt_functions->set_handler(qualifier, name, 425331766Sken (char *)value, &(ocs->tgt_ocs)); 426331766Sken } 427331766Sken } 428331766Sken 429331766Sken /* If I didn't know how to set this config value pass the request to each of my children */ 430331766Sken if (result != 0) { 431331766Sken ocs_device_lock(ocs); 432331766Sken ocs_list_foreach(&ocs->domain_list, domain) { 433331766Sken if ((domain->mgmt_functions) && (domain->mgmt_functions->set_handler)) { 434331766Sken result = domain->mgmt_functions->set_handler(qualifier, name, (char*)value, domain); 435331766Sken } 436331766Sken if (result == 0) { 437331766Sken break; 438331766Sken } 439331766Sken } 440331766Sken ocs_device_unlock(ocs); 441331766Sken } 442331766Sken 443331766Sken 444331766Sken } 445331766Sken 446331766Sken return result; 447331766Sken} 448331766Sken 449331766Sken/** 450331766Sken * @ingroup mgmt 451331766Sken * @brief Perform a management action. 452331766Sken * 453331766Sken * @par Description 454331766Sken * This is the top level "exec" handler for the driver. It 455331766Sken * performs the following: 456331766Sken * - Checks that the qualifier portion of the name begins with my qualifier (ocs). 457331766Sken * - If the remaining part of the name matches an action that is known at this level, 458331766Sken * calls the correct function to perform the action. 459331766Sken * - If the name is not known, sends the request to the back-ends to fulfill (if possible). 460331766Sken * - If the request has not been fulfilled by the back-end, passes the request to each of the 461331766Sken * children (domains) to have them (recursively) try to respond. 462331766Sken * 463331766Sken * In passing the request to other entities, the request is considered to be handled 464331766Sken * if the function returns 0. 465331766Sken * 466331766Sken * @param ocs Pointer to the ocs structure. 467331766Sken * @param action Name of the action to be performed. 468331766Sken * @param arg_in Pointer to an argument being passed to the action. 469331766Sken * @param arg_in_length Length of the argument pointed to by @c arg_in. 470331766Sken * @param arg_out Pointer to an argument being passed to the action. 471331766Sken * @param arg_out_length Length of the argument pointed to by @c arg_out. 472331766Sken * 473331766Sken * @return Returns 0 if the action was completed, or -1 otherwise. 474331766Sken * 475331766Sken * 476331766Sken */ 477331766Sken 478331766Skenint 479331766Skenocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in, 480331766Sken uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length) 481331766Sken{ 482331766Sken ocs_domain_t *domain; 483331766Sken int result = -1; 484331766Sken char qualifier[80]; 485331766Sken uint32_t i; 486331766Sken 487331766Sken snprintf(qualifier, sizeof(qualifier), "/ocs"); 488331766Sken 489331766Sken /* If it doesn't start with my qualifier I don't know what to do with it */ 490331766Sken if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) { 491331766Sken char *unqualified_name = action + strlen(qualifier) +1; 492331766Sken 493331766Sken /* See if it's an action I can perform */ 494331766Sken for (i=0;i<ARRAY_SIZE(mgmt_table); i++) { 495331766Sken if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) { 496331766Sken if (mgmt_table[i].action_handler) { 497331766Sken return mgmt_table[i].action_handler(ocs, action, arg_in, arg_in_length, 498331766Sken arg_out, arg_out_length); 499331766Sken } 500331766Sken 501331766Sken } 502331766Sken } 503331766Sken 504331766Sken if ((ocs->mgmt_functions) && (ocs->mgmt_functions->exec_handler)) { 505331766Sken result = ocs->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length, 506331766Sken arg_out, arg_out_length, ocs); 507331766Sken } 508331766Sken 509331766Sken if (result != 0) { 510331766Sken if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->exec_handler)) { 511331766Sken result = ocs->tgt_mgmt_functions->exec_handler(qualifier, action, 512331766Sken arg_in, arg_in_length, arg_out, arg_out_length, 513331766Sken &(ocs->tgt_ocs)); 514331766Sken } 515331766Sken } 516331766Sken 517331766Sken /* If I didn't know how to do this action pass the request to each of my children */ 518331766Sken if (result != 0) { 519331766Sken ocs_device_lock(ocs); 520331766Sken ocs_list_foreach(&ocs->domain_list, domain) { 521331766Sken if ((domain->mgmt_functions) && (domain->mgmt_functions->exec_handler)) { 522331766Sken result = domain->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length, arg_out, 523331766Sken arg_out_length, domain); 524331766Sken } 525331766Sken if (result == 0) { 526331766Sken break; 527331766Sken } 528331766Sken } 529331766Sken ocs_device_unlock(ocs); 530331766Sken } 531331766Sken 532331766Sken } 533331766Sken 534331766Sken return result; 535331766Sken} 536331766Sken 537331766Skenvoid 538331766Skenocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf) 539331766Sken{ 540331766Sken ocs_domain_t *domain; 541331766Sken uint32_t i; 542331766Sken 543331766Sken ocs_mgmt_start_unnumbered_section(textbuf, "ocs"); 544331766Sken 545331766Sken for (i=0;i<ARRAY_SIZE(mgmt_table);i++) { 546331766Sken if (mgmt_table[i].get_handler) { 547331766Sken mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf); 548331766Sken } else if (mgmt_table[i].action_handler) { 549331766Sken /* No get_handler, but there's an action_handler. Just report 550331766Sken the name */ 551331766Sken ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, mgmt_table[i].name); 552331766Sken } 553331766Sken } 554331766Sken 555331766Sken if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_all_handler)) { 556331766Sken ocs->mgmt_functions->get_all_handler(textbuf, ocs); 557331766Sken } 558331766Sken 559331766Sken if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_all_handler)) { 560331766Sken ocs->tgt_mgmt_functions->get_all_handler(textbuf, &(ocs->tgt_ocs)); 561331766Sken } 562331766Sken 563331766Sken ocs_device_lock(ocs); 564331766Sken ocs_list_foreach(&ocs->domain_list, domain) { 565331766Sken if ((domain->mgmt_functions) && (domain->mgmt_functions->get_all_handler)) { 566331766Sken domain->mgmt_functions->get_all_handler(textbuf, domain); 567331766Sken } 568331766Sken } 569331766Sken ocs_device_unlock(ocs); 570331766Sken 571331766Sken ocs_mgmt_end_unnumbered_section(textbuf, "ocs"); 572331766Sken} 573331766Sken 574331766Sken#if defined(OCS_INCLUDE_RAMD) 575331766Skenstatic int32_t 576331766Skenocs_mgmt_read_phys(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length) 577331766Sken{ 578331766Sken uint32_t length; 579331766Sken char addr_str[80]; 580331766Sken uintptr_t target_addr; 581331766Sken void* vaddr = NULL; 582331766Sken ocs_ramdisc_t **ramdisc_array; 583331766Sken uint32_t ramdisc_count; 584331766Sken 585331766Sken 586331766Sken if ((arg_in == NULL) || 587331766Sken (arg_in_length == 0) || 588331766Sken (arg_out == NULL) || 589331766Sken (arg_out_length == 0)) { 590331766Sken return -1; 591331766Sken } 592331766Sken 593331766Sken if (arg_in_length > 80) { 594331766Sken arg_in_length = 80; 595331766Sken } 596331766Sken 597331766Sken if (ocs_copy_from_user(addr_str, arg_in, arg_in_length)) { 598331766Sken ocs_log_test(ocs, "Failed to copy addr from user\n"); 599331766Sken return -EFAULT; 600331766Sken } 601331766Sken 602331766Sken target_addr = (uintptr_t)ocs_strtoul(addr_str, NULL, 0); 603331766Sken /* addr_str must be the physical address of a buffer that was reported 604331766Sken * in an SGL. Search ramdiscs looking for a segment that contains that 605331766Sken * physical address 606331766Sken */ 607331766Sken 608331766Sken if (ocs->tgt_ocs.use_global_ramd) { 609331766Sken /* Only one target */ 610331766Sken ramdisc_count = ocs->tgt_ocs.rdisc_count; 611331766Sken ramdisc_array = ocs->tgt_ocs.rdisc; 612331766Sken vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr); 613331766Sken } else { 614331766Sken /* Multiple targets. Each target is on a sport */ 615331766Sken uint32_t domain_idx; 616331766Sken 617331766Sken for (domain_idx=0; domain_idx<ocs->domain_instance_count; domain_idx++) { 618331766Sken ocs_domain_t *domain; 619331766Sken uint32_t sport_idx; 620331766Sken 621331766Sken domain = ocs_domain_get_instance(ocs, domain_idx); 622331766Sken for (sport_idx=0; sport_idx < domain->sport_instance_count; sport_idx++) { 623331766Sken ocs_sport_t *sport; 624331766Sken 625331766Sken sport = ocs_sport_get_instance(domain, sport_idx); 626331766Sken ramdisc_count = sport->tgt_sport.rdisc_count; 627331766Sken ramdisc_array = sport->tgt_sport.rdisc; 628331766Sken vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr); 629331766Sken 630331766Sken if (vaddr != NULL) { 631331766Sken break; 632331766Sken } 633331766Sken } 634331766Sken } 635331766Sken } 636331766Sken 637331766Sken 638331766Sken 639331766Sken 640331766Sken length = arg_out_length; 641331766Sken 642331766Sken if (vaddr != NULL) { 643331766Sken 644331766Sken if (ocs_copy_to_user(arg_out, vaddr, length)) { 645331766Sken ocs_log_test(ocs, "Failed to copy buffer to user\n"); 646331766Sken return -EFAULT; 647331766Sken } 648331766Sken 649331766Sken return 0; 650331766Sken } else { 651331766Sken 652331766Sken return -EFAULT; 653331766Sken } 654331766Sken 655331766Sken} 656331766Sken 657331766Sken/* 658331766Sken * This function searches a target for a given physical address. 659331766Sken * The target is made up of a number of LUNs, each represented by 660331766Sken * a ocs_ramdisc_t. 661331766Sken */ 662331766Skenstatic void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr) 663331766Sken{ 664331766Sken void *vaddr = NULL; 665331766Sken uint32_t ramdisc_idx; 666331766Sken 667331766Sken /* Check each ramdisc */ 668331766Sken for (ramdisc_idx=0; ramdisc_idx<ramdisc_count; ramdisc_idx++) { 669331766Sken uint32_t segment_idx; 670331766Sken ocs_ramdisc_t *rdisc; 671331766Sken rdisc = ramdisc_array[ramdisc_idx]; 672331766Sken /* Check each segment in the ramdisc */ 673331766Sken for (segment_idx=0; segment_idx<rdisc->segment_count; segment_idx++) { 674331766Sken ramdisc_segment_t *segment = rdisc->segments[segment_idx]; 675331766Sken uintptr_t segment_start; 676331766Sken uintptr_t segment_end; 677331766Sken uint32_t offset; 678331766Sken 679331766Sken segment_start = segment->data_segment.phys; 680331766Sken segment_end = segment->data_segment.phys + segment->data_segment.size - 1; 681331766Sken if ((target_addr >= segment_start) && (target_addr <= segment_end)) { 682331766Sken /* Found the target address */ 683331766Sken offset = target_addr - segment_start; 684331766Sken vaddr = (uint32_t*)segment->data_segment.virt + offset; 685331766Sken } 686331766Sken 687331766Sken if (rdisc->dif_separate) { 688331766Sken segment_start = segment->dif_segment.phys; 689331766Sken segment_end = segment->data_segment.phys + segment->dif_segment.size - 1; 690331766Sken if ((target_addr >= segment_start) && (target_addr <= segment_end)) { 691331766Sken /* Found the target address */ 692331766Sken offset = target_addr - segment_start; 693331766Sken vaddr = (uint32_t*)segment->dif_segment.virt + offset; 694331766Sken } 695331766Sken } 696331766Sken 697331766Sken if (vaddr != NULL) { 698331766Sken break; 699331766Sken } 700331766Sken 701331766Sken } 702331766Sken 703331766Sken if (vaddr != NULL) { 704331766Sken break; 705331766Sken } 706331766Sken 707331766Sken 708331766Sken } 709331766Sken 710331766Sken return vaddr; 711331766Sken} 712331766Sken#endif 713331766Sken 714331766Sken 715331766Sken 716331766Skenstatic int32_t 717331766Skenocs_mgmt_firmware_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length) 718331766Sken{ 719331766Sken int rc = 0; 720331766Sken int index = 0; 721331766Sken uint8_t bus, dev, func; 722331766Sken ocs_t *other_ocs; 723331766Sken 724331766Sken ocs_get_bus_dev_func(ocs, &bus, &dev, &func); 725331766Sken 726331766Sken ocs_log_debug(ocs, "Resetting port\n"); 727331766Sken if (ocs_hw_reset(&ocs->hw, OCS_HW_RESET_FIRMWARE)) { 728331766Sken ocs_log_test(ocs, "failed to reset port\n"); 729331766Sken rc = -1; 730331766Sken } else { 731331766Sken ocs_log_debug(ocs, "successfully reset port\n"); 732331766Sken 733331766Sken /* now reset all functions on the same device */ 734331766Sken 735331766Sken while ((other_ocs = ocs_get_instance(index++)) != NULL) { 736331766Sken uint8_t other_bus, other_dev, other_func; 737331766Sken 738331766Sken ocs_get_bus_dev_func(other_ocs, &other_bus, &other_dev, &other_func); 739331766Sken 740331766Sken if ((bus == other_bus) && (dev == other_dev)) { 741331766Sken if (other_ocs->hw.state != 742331766Sken OCS_HW_STATE_UNINITIALIZED) { 743331766Sken other_ocs->hw.state = 744331766Sken OCS_HW_STATE_QUEUES_ALLOCATED; 745331766Sken } 746331766Sken 747331766Sken ocs_device_detach(other_ocs); 748331766Sken if (ocs_device_attach(other_ocs)) { 749331766Sken ocs_log_err(other_ocs, 750331766Sken "device %d attach failed \n", index); 751331766Sken rc = -1; 752331766Sken } 753331766Sken } 754331766Sken } 755331766Sken } 756331766Sken return rc; 757331766Sken} 758331766Sken 759331766Skenstatic int32_t 760331766Skenocs_mgmt_function_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length) 761331766Sken{ 762331766Sken int32_t rc; 763331766Sken 764331766Sken ocs_device_detach(ocs); 765331766Sken rc = ocs_device_attach(ocs); 766331766Sken 767331766Sken return rc; 768331766Sken} 769331766Sken 770331766Skenstatic int32_t 771331766Skenocs_mgmt_firmware_write(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length) 772331766Sken{ 773331766Sken int rc = 0; 774331766Sken uint32_t bytes_left; 775331766Sken uint32_t xfer_size; 776331766Sken uint32_t offset; 777331766Sken uint8_t *userp; 778331766Sken ocs_dma_t dma; 779331766Sken int last = 0; 780331766Sken ocs_mgmt_fw_write_result_t result; 781331766Sken uint32_t change_status = 0; 782331766Sken char status_str[80]; 783331766Sken 784331766Sken ocs_sem_init(&(result.semaphore), 0, "fw_write"); 785331766Sken 786331766Sken bytes_left = buf_len; 787331766Sken offset = 0; 788331766Sken userp = (uint8_t *)buf; 789331766Sken 790331766Sken if (ocs_dma_alloc(ocs, &dma, FW_WRITE_BUFSIZE, 4096)) { 791331766Sken ocs_log_err(ocs, "ocs_mgmt_firmware_write: malloc failed"); 792331766Sken return -ENOMEM; 793331766Sken } 794331766Sken 795331766Sken while (bytes_left > 0) { 796331766Sken 797331766Sken 798331766Sken if (bytes_left > FW_WRITE_BUFSIZE) { 799331766Sken xfer_size = FW_WRITE_BUFSIZE; 800331766Sken } else { 801331766Sken xfer_size = bytes_left; 802331766Sken } 803331766Sken 804331766Sken /* Copy xfer_size bytes from user space to kernel buffer */ 805331766Sken if (ocs_copy_from_user(dma.virt, userp, xfer_size)) { 806331766Sken rc = -EFAULT; 807331766Sken break; 808331766Sken } 809331766Sken 810331766Sken /* See if this is the last block */ 811331766Sken if (bytes_left == xfer_size) { 812331766Sken last = 1; 813331766Sken } 814331766Sken 815331766Sken /* Send the HW command */ 816331766Sken ocs_hw_firmware_write(&ocs->hw, &dma, xfer_size, offset, last, ocs_mgmt_fw_write_cb, &result); 817331766Sken 818331766Sken /* Wait for semaphore to be signaled when the command completes 819331766Sken * TODO: Should there be a timeout on this? If so, how long? */ 820331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 821331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 822331766Sken rc = -ENXIO; 823331766Sken break; 824331766Sken } 825331766Sken 826331766Sken if (result.actual_xfer == 0) { 827331766Sken ocs_log_test(ocs, "actual_write_length is %d\n", result.actual_xfer); 828331766Sken rc = -EFAULT; 829331766Sken break; 830331766Sken } 831331766Sken 832331766Sken /* Check status */ 833331766Sken if (result.status != 0) { 834331766Sken ocs_log_test(ocs, "write returned status %d\n", result.status); 835331766Sken rc = -EFAULT; 836331766Sken break; 837331766Sken } 838331766Sken 839331766Sken if (last) { 840331766Sken change_status = result.change_status; 841331766Sken } 842331766Sken 843331766Sken bytes_left -= result.actual_xfer; 844331766Sken offset += result.actual_xfer; 845331766Sken userp += result.actual_xfer; 846331766Sken 847331766Sken } 848331766Sken 849331766Sken /* Create string with status and copy to userland */ 850331766Sken if ((arg_out_length > 0) && (arg_out != NULL)) { 851331766Sken if (arg_out_length > sizeof(status_str)) { 852331766Sken arg_out_length = sizeof(status_str); 853331766Sken } 854343371Smarkj ocs_memset(status_str, 0, sizeof(status_str)); 855331766Sken ocs_snprintf(status_str, arg_out_length, "%d", change_status); 856331766Sken if (ocs_copy_to_user(arg_out, status_str, arg_out_length)) { 857331766Sken ocs_log_test(ocs, "copy to user failed for change_status\n"); 858331766Sken } 859331766Sken } 860331766Sken 861331766Sken 862331766Sken ocs_dma_free(ocs, &dma); 863331766Sken 864331766Sken return rc; 865331766Sken} 866331766Sken 867331766Skenstatic void 868331766Skenocs_mgmt_fw_write_cb(int32_t status, uint32_t actual_write_length, uint32_t change_status, void *arg) 869331766Sken{ 870331766Sken ocs_mgmt_fw_write_result_t *result = arg; 871331766Sken 872331766Sken result->status = status; 873331766Sken result->actual_xfer = actual_write_length; 874331766Sken result->change_status = change_status; 875331766Sken 876331766Sken ocs_sem_v(&(result->semaphore)); 877331766Sken} 878331766Sken 879331766Skentypedef struct ocs_mgmt_sfp_result { 880331766Sken ocs_sem_t semaphore; 881331766Sken ocs_lock_t cb_lock; 882331766Sken int32_t running; 883331766Sken int32_t status; 884331766Sken uint32_t bytes_read; 885331766Sken uint32_t page_data[32]; 886331766Sken} ocs_mgmt_sfp_result_t; 887331766Sken 888331766Skenstatic void 889331766Skenocs_mgmt_sfp_cb(void *os, int32_t status, uint32_t bytes_read, uint32_t *data, void *arg) 890331766Sken{ 891331766Sken ocs_mgmt_sfp_result_t *result = arg; 892331766Sken ocs_t *ocs = os; 893331766Sken 894331766Sken ocs_lock(&(result->cb_lock)); 895331766Sken result->running++; 896331766Sken if(result->running == 2) { 897331766Sken /* get_sfp() has timed out */ 898331766Sken ocs_unlock(&(result->cb_lock)); 899331766Sken ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t)); 900331766Sken return; 901331766Sken } 902331766Sken 903331766Sken result->status = status; 904331766Sken result->bytes_read = bytes_read; 905331766Sken ocs_memcpy(&result->page_data, data, SFP_PAGE_SIZE); 906331766Sken 907331766Sken ocs_sem_v(&(result->semaphore)); 908331766Sken ocs_unlock(&(result->cb_lock)); 909331766Sken} 910331766Sken 911331766Skenstatic int32_t 912331766Skenocs_mgmt_get_sfp(ocs_t *ocs, uint16_t page, void *buf, uint32_t buf_len) 913331766Sken{ 914331766Sken int rc = 0; 915331766Sken ocs_mgmt_sfp_result_t *result = ocs_malloc(ocs, sizeof(ocs_mgmt_sfp_result_t), OCS_M_ZERO | OCS_M_NOWAIT);; 916331766Sken 917331766Sken ocs_sem_init(&(result->semaphore), 0, "get_sfp"); 918331766Sken ocs_lock_init(ocs, &(result->cb_lock), "get_sfp"); 919331766Sken 920331766Sken /* Send the HW command */ 921331766Sken ocs_hw_get_sfp(&ocs->hw, page, ocs_mgmt_sfp_cb, result); 922331766Sken 923331766Sken /* Wait for semaphore to be signaled when the command completes */ 924331766Sken if (ocs_sem_p(&(result->semaphore), 5 * 1000 * 1000) != 0) { 925331766Sken /* Timed out, callback will free memory */ 926331766Sken ocs_lock(&(result->cb_lock)); 927331766Sken result->running++; 928331766Sken if(result->running == 1) { 929331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 930331766Sken ocs_unlock(&(result->cb_lock)); 931331766Sken return (-ENXIO); 932331766Sken } 933331766Sken /* sfp_cb() has already executed, proceed as normal */ 934331766Sken ocs_unlock(&(result->cb_lock)); 935331766Sken } 936331766Sken 937331766Sken /* Check status */ 938331766Sken if (result->status != 0) { 939331766Sken ocs_log_test(ocs, "read_transceiver_data returned status %d\n", 940331766Sken result->status); 941331766Sken rc = -EFAULT; 942331766Sken } 943331766Sken 944331766Sken if (rc == 0) { 945331766Sken rc = (result->bytes_read > buf_len ? buf_len : result->bytes_read); 946331766Sken /* Copy the results back to the supplied buffer */ 947331766Sken ocs_memcpy(buf, result->page_data, rc); 948331766Sken } 949331766Sken 950331766Sken ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t)); 951331766Sken return rc; 952331766Sken} 953331766Sken 954331766Skenstatic int32_t 955331766Skenocs_mgmt_force_assert(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length) 956331766Sken{ 957331766Sken ocs_assert(FALSE, 0); 958331766Sken} 959331766Sken 960331766Skenstatic void 961331766Skenget_nodes_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 962331766Sken{ 963331766Sken ocs_xport_t *xport = ocs->xport; 964331766Sken 965331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "nodes_count", "%d", xport->nodes_count); 966331766Sken} 967331766Sken 968331766Skenstatic void 969331766Skenget_driver_version(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 970331766Sken{ 971331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "driver_version", ocs->driver_version); 972331766Sken} 973331766Sken 974331766Skenstatic void 975331766Skenget_desc(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 976331766Sken{ 977331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "desc", ocs->desc); 978331766Sken} 979331766Sken 980331766Skenstatic void 981331766Skenget_fw_rev(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 982331766Sken{ 983331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev", ocs_hw_get_ptr(&ocs->hw, OCS_HW_FW_REV)); 984331766Sken} 985331766Sken 986331766Skenstatic void 987331766Skenget_fw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 988331766Sken{ 989331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev2", ocs_hw_get_ptr(&ocs->hw, OCS_HW_FW_REV2)); 990331766Sken} 991331766Sken 992331766Skenstatic void 993331766Skenget_ipl(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 994331766Sken{ 995331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ipl", ocs_hw_get_ptr(&ocs->hw, OCS_HW_IPL)); 996331766Sken} 997331766Sken 998331766Skenstatic void 999331766Skenget_hw_rev1(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1000331766Sken{ 1001331766Sken uint32_t value; 1002331766Sken 1003331766Sken ocs_hw_get(&ocs->hw, OCS_HW_HW_REV1, &value); 1004331766Sken 1005331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev1", "%u", value); 1006331766Sken} 1007331766Sken 1008331766Skenstatic void 1009331766Skenget_hw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1010331766Sken{ 1011331766Sken uint32_t value; 1012331766Sken 1013331766Sken ocs_hw_get(&ocs->hw, OCS_HW_HW_REV2, &value); 1014331766Sken 1015331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev2", "%u", value); 1016331766Sken} 1017331766Sken 1018331766Skenstatic void 1019331766Skenget_hw_rev3(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1020331766Sken{ 1021331766Sken uint32_t value; 1022331766Sken ocs_hw_get(&ocs->hw, OCS_HW_HW_REV3, &value); 1023331766Sken 1024331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev3", "%u", value); 1025331766Sken} 1026331766Sken 1027331766Skenstatic void 1028331766Skenget_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1029331766Sken{ 1030331766Sken uint64_t *wwnn; 1031331766Sken 1032331766Sken wwnn = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_NODE); 1033331766Sken 1034331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "0x%llx", (unsigned long long)ocs_htobe64(*wwnn)); 1035331766Sken} 1036331766Sken 1037331766Skenstatic void 1038331766Skenget_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1039331766Sken{ 1040331766Sken uint64_t *wwpn; 1041331766Sken 1042331766Sken wwpn = ocs_hw_get_ptr(&ocs->hw, OCS_HW_WWN_PORT); 1043331766Sken 1044331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "0x%llx", (unsigned long long)ocs_htobe64(*wwpn)); 1045331766Sken} 1046331766Sken 1047331766Skenstatic void 1048331766Skenget_fcid(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1049331766Sken{ 1050331766Sken 1051331766Sken if (ocs->domain && ocs->domain->attached) { 1052331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "0x%06x", 1053331766Sken ocs->domain->sport->fc_id); 1054331766Sken } else { 1055331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fc_id", "UNKNOWN"); 1056331766Sken } 1057331766Sken 1058331766Sken} 1059331766Sken 1060331766Skenstatic void 1061331766Skenget_sn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1062331766Sken{ 1063331766Sken uint8_t *pserial; 1064331766Sken uint32_t len; 1065331766Sken char sn_buf[256]; 1066331766Sken 1067331766Sken pserial = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_SERIALNUMBER); 1068331766Sken if (pserial) { 1069331766Sken len = *pserial ++; 1070331766Sken strncpy(sn_buf, (char*)pserial, len); 1071331766Sken sn_buf[len] = '\0'; 1072331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sn", sn_buf); 1073331766Sken } 1074331766Sken} 1075331766Sken 1076331766Skenstatic void 1077331766Skenget_pn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1078331766Sken{ 1079331766Sken uint8_t *pserial; 1080331766Sken uint32_t len; 1081331766Sken char sn_buf[256]; 1082331766Sken 1083331766Sken pserial = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_PARTNUMBER); 1084331766Sken if (pserial) { 1085331766Sken len = *pserial ++; 1086331766Sken strncpy(sn_buf, (char*)pserial, len); 1087331766Sken sn_buf[len] = '\0'; 1088331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", sn_buf); 1089331766Sken } else { 1090331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", ocs->model); 1091331766Sken } 1092331766Sken} 1093331766Sken 1094331766Skenstatic void 1095331766Skenget_sli4_intf_reg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1096331766Sken{ 1097331766Sken 1098331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "sli4_intf_reg", "0x%04x", 1099331766Sken ocs_config_read32(ocs, SLI4_INTF_REG)); 1100331766Sken} 1101331766Sken 1102331766Skenstatic void 1103331766Skenget_phy_port_num(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1104331766Sken{ 1105331766Sken char *phy_port = NULL; 1106331766Sken 1107331766Sken phy_port = ocs_scsi_get_property_ptr(ocs, OCS_SCSI_PORTNUM); 1108331766Sken if (phy_port) { 1109331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "phy_port_num", phy_port); 1110331766Sken } else { 1111331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "phy_port_num", "unknown"); 1112331766Sken } 1113331766Sken} 1114331766Skenstatic void 1115331766Skenget_asic_id(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1116331766Sken{ 1117331766Sken 1118331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "asic_id_reg", "0x%04x", 1119331766Sken ocs_config_read32(ocs, SLI4_ASIC_ID_REG)); 1120331766Sken} 1121331766Sken 1122331766Skenstatic void 1123331766Skenget_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1124331766Sken{ 1125331766Sken uint32_t family; 1126331766Sken uint32_t asic_id; 1127331766Sken uint32_t asic_gen_num; 1128331766Sken uint32_t asic_rev_num; 1129331766Sken uint32_t rev_id; 1130331766Sken char result_buf[80]; 1131331766Sken char tmp_buf[80]; 1132331766Sken 1133331766Sken family = (ocs_config_read32(ocs, SLI4_INTF_REG) & 0x00000f00) >> 8; 1134331766Sken asic_id = ocs_config_read32(ocs, SLI4_ASIC_ID_REG); 1135331766Sken asic_rev_num = asic_id & 0xff; 1136331766Sken asic_gen_num = (asic_id & 0xff00) >> 8; 1137331766Sken 1138331766Sken rev_id = ocs_config_read32(ocs, SLI4_PCI_CLASS_REVISION) & 0xff; 1139331766Sken 1140331766Sken switch(family) { 1141331766Sken case 0x00: 1142331766Sken /* BE2 */ 1143331766Sken ocs_strncpy(result_buf, "BE2 A", sizeof(result_buf)); 1144331766Sken ocs_snprintf(tmp_buf, 2, "%d", rev_id); 1145331766Sken strcat(result_buf, tmp_buf); 1146331766Sken break; 1147331766Sken case 0x01: 1148331766Sken /* BE3 */ 1149331766Sken ocs_strncpy(result_buf, "BE3", sizeof(result_buf)); 1150331766Sken if (rev_id >= 0x10) { 1151331766Sken strcat(result_buf, "-R"); 1152331766Sken } 1153331766Sken ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A'); 1154331766Sken strcat(result_buf, tmp_buf); 1155331766Sken ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f); 1156331766Sken strcat(result_buf, tmp_buf); 1157331766Sken break; 1158331766Sken case 0x02: 1159331766Sken /* Skyhawk A0 */ 1160331766Sken ocs_strncpy(result_buf, "Skyhawk A0", sizeof(result_buf)); 1161331766Sken break; 1162331766Sken case 0x0a: 1163331766Sken /* Lancer A0 */ 1164331766Sken ocs_strncpy(result_buf, "Lancer A", sizeof(result_buf)); 1165331766Sken ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f); 1166331766Sken strcat(result_buf, tmp_buf); 1167331766Sken break; 1168331766Sken case 0x0b: 1169331766Sken /* Lancer B0 or D0 */ 1170331766Sken ocs_strncpy(result_buf, "Lancer", sizeof(result_buf)); 1171331766Sken ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A'); 1172331766Sken strcat(result_buf, tmp_buf); 1173331766Sken ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f); 1174331766Sken strcat(result_buf, tmp_buf); 1175331766Sken break; 1176331766Sken case 0x0c: 1177331766Sken ocs_strncpy(result_buf, "Lancer G6", sizeof(result_buf)); 1178331766Sken break; 1179331766Sken case 0x0f: 1180331766Sken /* Refer to ASIC_ID */ 1181331766Sken switch(asic_gen_num) { 1182331766Sken case 0x00: 1183331766Sken ocs_strncpy(result_buf, "BE2", sizeof(result_buf)); 1184331766Sken break; 1185331766Sken case 0x03: 1186331766Sken ocs_strncpy(result_buf, "BE3-R", sizeof(result_buf)); 1187331766Sken break; 1188331766Sken case 0x04: 1189331766Sken ocs_strncpy(result_buf, "Skyhawk-R", sizeof(result_buf)); 1190331766Sken break; 1191331766Sken case 0x05: 1192331766Sken ocs_strncpy(result_buf, "Corsair", sizeof(result_buf)); 1193331766Sken break; 1194331766Sken case 0x0b: 1195331766Sken ocs_strncpy(result_buf, "Lancer", sizeof(result_buf)); 1196331766Sken break; 1197331766Sken case 0x0c: 1198331766Sken ocs_strncpy(result_buf, "LancerG6", sizeof(result_buf)); 1199331766Sken break; 1200331766Sken default: 1201331766Sken ocs_strncpy(result_buf, "Unknown", sizeof(result_buf)); 1202331766Sken } 1203331766Sken if (ocs_strcmp(result_buf, "Unknown") != 0) { 1204331766Sken ocs_snprintf(tmp_buf, 3, " %c", ((asic_rev_num & 0xf0) >> 4) + 'A'); 1205331766Sken strcat(result_buf, tmp_buf); 1206331766Sken ocs_snprintf(tmp_buf, 2, "%d", asic_rev_num & 0x0f); 1207331766Sken strcat(result_buf, tmp_buf); 1208331766Sken } 1209331766Sken break; 1210331766Sken default: 1211331766Sken ocs_strncpy(result_buf, "Unknown", sizeof(result_buf)); 1212331766Sken } 1213331766Sken 1214331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "chip_type", result_buf); 1215331766Sken 1216331766Sken} 1217331766Sken 1218331766Skenstatic void 1219331766Skenget_pci_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1220331766Sken{ 1221331766Sken 1222331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_vendor", "0x%04x", ocs->pci_vendor); 1223331766Sken} 1224331766Sken 1225331766Skenstatic void 1226331766Skenget_pci_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1227331766Sken{ 1228331766Sken 1229331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_device", "0x%04x", ocs->pci_device); 1230331766Sken} 1231331766Sken 1232331766Skenstatic void 1233331766Skenget_pci_subsystem_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1234331766Sken{ 1235331766Sken 1236331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_vendor", "0x%04x", ocs->pci_subsystem_vendor); 1237331766Sken} 1238331766Sken 1239331766Skenstatic void 1240331766Skenget_pci_subsystem_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1241331766Sken{ 1242331766Sken 1243331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_device", "0x%04x", ocs->pci_subsystem_device); 1244331766Sken} 1245331766Sken 1246331766Skenstatic void 1247331766Skenget_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1248331766Sken{ 1249331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tgt_rscn_delay", "%ld", (unsigned long)ocs->tgt_rscn_delay_msec / 1000); 1250331766Sken} 1251331766Sken 1252331766Skenstatic void 1253331766Skenget_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1254331766Sken{ 1255331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tgt_rscn_period", "%ld", (unsigned long)ocs->tgt_rscn_period_msec / 1000); 1256331766Sken} 1257331766Sken 1258331766Skenstatic void 1259331766Skenget_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1260331766Sken{ 1261331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_cmd", "%d", 1262331766Sken (ocs->err_injection == INJECT_DROP_CMD ? 1:0)); 1263331766Sken} 1264331766Sken 1265331766Skenstatic void 1266331766Skenget_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1267331766Sken{ 1268331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_free_drop_cmd", "%d", 1269331766Sken (ocs->err_injection == INJECT_FREE_DROPPED ? 1:0)); 1270331766Sken} 1271331766Sken 1272331766Skenstatic void 1273331766Skenget_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1274331766Sken{ 1275331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_data", "%d", 1276331766Sken (ocs->err_injection == INJECT_DROP_DATA ? 1:0)); 1277331766Sken} 1278331766Sken 1279331766Skenstatic void 1280331766Skenget_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1281331766Sken{ 1282331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_resp", "%d", 1283331766Sken (ocs->err_injection == INJECT_DROP_RESP ? 1:0)); 1284331766Sken} 1285331766Sken 1286331766Skenstatic void 1287331766Skenget_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1288331766Sken{ 1289331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "cmd_err_inject", "0x%02x", ocs->cmd_err_inject); 1290331766Sken} 1291331766Sken 1292331766Skenstatic void 1293331766Skenget_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1294331766Sken{ 1295331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "cmd_delay_value", "%ld", (unsigned long)ocs->delay_value_msec); 1296331766Sken} 1297331766Sken 1298331766Skenstatic void 1299331766Skenget_businfo(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1300331766Sken{ 1301331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "businfo", ocs->businfo); 1302331766Sken} 1303331766Sken 1304331766Skenstatic void 1305331766Skenget_sfp_a0(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1306331766Sken{ 1307331766Sken uint8_t *page_data; 1308331766Sken char *buf; 1309331766Sken int i; 1310331766Sken int32_t bytes_read; 1311331766Sken 1312331766Sken page_data = ocs_malloc(ocs, SFP_PAGE_SIZE, OCS_M_ZERO | OCS_M_NOWAIT); 1313331766Sken if (page_data == NULL) { 1314331766Sken return; 1315331766Sken } 1316331766Sken 1317331766Sken buf = ocs_malloc(ocs, (SFP_PAGE_SIZE * 3) + 1, OCS_M_ZERO | OCS_M_NOWAIT); 1318331766Sken if (buf == NULL) { 1319331766Sken ocs_free(ocs, page_data, SFP_PAGE_SIZE); 1320331766Sken return; 1321331766Sken } 1322331766Sken 1323331766Sken bytes_read = ocs_mgmt_get_sfp(ocs, 0xa0, page_data, SFP_PAGE_SIZE); 1324331766Sken 1325331766Sken if (bytes_read <= 0) { 1326331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", "(unknown)"); 1327331766Sken } else { 1328331766Sken char *d = buf; 1329331766Sken uint8_t *s = page_data; 1330331766Sken int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1; 1331331766Sken int bytes_added; 1332331766Sken 1333331766Sken for (i = 0; i < bytes_read; i++) { 1334331766Sken bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s); 1335331766Sken ++s; 1336331766Sken d += bytes_added; 1337331766Sken buffer_remaining -= bytes_added; 1338331766Sken } 1339331766Sken *d = '\0'; 1340331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", buf); 1341331766Sken } 1342331766Sken 1343331766Sken ocs_free(ocs, page_data, SFP_PAGE_SIZE); 1344331766Sken ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE) + 1); 1345331766Sken} 1346331766Sken 1347331766Skenstatic void 1348331766Skenget_sfp_a2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1349331766Sken{ 1350331766Sken uint8_t *page_data; 1351331766Sken char *buf; 1352331766Sken int i; 1353331766Sken int32_t bytes_read; 1354331766Sken 1355331766Sken page_data = ocs_malloc(ocs, SFP_PAGE_SIZE, OCS_M_ZERO | OCS_M_NOWAIT); 1356331766Sken if (page_data == NULL) { 1357331766Sken return; 1358331766Sken } 1359331766Sken 1360331766Sken buf = ocs_malloc(ocs, (SFP_PAGE_SIZE * 3) + 1, OCS_M_ZERO | OCS_M_NOWAIT); 1361331766Sken if (buf == NULL) { 1362331766Sken ocs_free(ocs, page_data, SFP_PAGE_SIZE); 1363331766Sken return; 1364331766Sken } 1365331766Sken 1366331766Sken bytes_read = ocs_mgmt_get_sfp(ocs, 0xa2, page_data, SFP_PAGE_SIZE); 1367331766Sken 1368331766Sken if (bytes_read <= 0) { 1369331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", "(unknown)"); 1370331766Sken } else { 1371331766Sken char *d = buf; 1372331766Sken uint8_t *s = page_data; 1373331766Sken int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1; 1374331766Sken int bytes_added; 1375331766Sken 1376331766Sken for (i=0; i < bytes_read; i++) { 1377331766Sken bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s); 1378331766Sken ++s; 1379331766Sken d += bytes_added; 1380331766Sken buffer_remaining -= bytes_added; 1381331766Sken } 1382331766Sken *d = '\0'; 1383331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", buf); 1384331766Sken } 1385331766Sken 1386331766Sken ocs_free(ocs, page_data, SFP_PAGE_SIZE); 1387331766Sken ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE) + 1); 1388331766Sken} 1389331766Sken 1390331766Skenstatic void 1391331766Skenget_debug_mq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1392331766Sken{ 1393331766Sken 1394331766Sken ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_mq_dump", 1395331766Sken ocs_debug_is_enabled(OCS_DEBUG_ENABLE_MQ_DUMP)); 1396331766Sken} 1397331766Sken 1398331766Skenstatic void 1399331766Skenget_debug_cq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1400331766Sken{ 1401331766Sken 1402331766Sken ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_cq_dump", 1403331766Sken ocs_debug_is_enabled(OCS_DEBUG_ENABLE_CQ_DUMP)); 1404331766Sken} 1405331766Sken 1406331766Skenstatic void 1407331766Skenget_debug_wq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1408331766Sken{ 1409331766Sken ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_wq_dump", 1410331766Sken ocs_debug_is_enabled(OCS_DEBUG_ENABLE_WQ_DUMP)); 1411331766Sken} 1412331766Sken 1413331766Skenstatic void 1414331766Skenget_debug_eq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1415331766Sken{ 1416331766Sken ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_eq_dump", 1417331766Sken ocs_debug_is_enabled(OCS_DEBUG_ENABLE_EQ_DUMP)); 1418331766Sken} 1419331766Sken 1420331766Skenstatic void 1421331766Skenget_logmask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1422331766Sken{ 1423331766Sken 1424331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "logmask", "0x%02x", ocs->logmask); 1425331766Sken 1426331766Sken} 1427331766Sken 1428331766Skenstatic void 1429331766Skenget_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1430331766Sken{ 1431331766Sken 1432331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "loglevel", "%d", loglevel); 1433331766Sken 1434331766Sken} 1435331766Sken 1436331766Skenstatic void 1437331766Skenget_current_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1438331766Sken{ 1439331766Sken uint32_t value; 1440331766Sken 1441331766Sken ocs_hw_get(&(ocs->hw), OCS_HW_LINK_SPEED, &value); 1442331766Sken 1443331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "current_speed", "%d", value); 1444331766Sken} 1445331766Sken 1446331766Skenstatic void 1447331766Skenget_configured_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1448331766Sken{ 1449331766Sken uint32_t value; 1450331766Sken 1451331766Sken ocs_hw_get(&(ocs->hw), OCS_HW_LINK_CONFIG_SPEED, &value); 1452331766Sken if (value == 0) { 1453331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_speed", "auto"); 1454331766Sken } else { 1455331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "configured_speed", "%d", value); 1456331766Sken } 1457331766Sken 1458331766Sken} 1459331766Sken 1460331766Skenstatic void 1461331766Skenget_current_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1462331766Sken{ 1463331766Sken uint32_t value; 1464331766Sken 1465331766Sken ocs_hw_get(&(ocs->hw), OCS_HW_TOPOLOGY, &value); 1466331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "current_topology", "%d", value); 1467331766Sken 1468331766Sken} 1469331766Sken 1470331766Skenstatic void 1471331766Skenget_configured_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1472331766Sken{ 1473331766Sken uint32_t value; 1474331766Sken 1475331766Sken ocs_hw_get(&(ocs->hw), OCS_HW_CONFIG_TOPOLOGY, &value); 1476331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "configured_topology", "%d", value); 1477331766Sken 1478331766Sken} 1479331766Sken 1480331766Skenstatic void 1481331766Skenget_current_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1482331766Sken{ 1483331766Sken ocs_xport_stats_t value; 1484331766Sken 1485331766Sken if (ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value) == 0) { 1486331766Sken if (value.value == OCS_XPORT_PORT_ONLINE) { 1487331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_link_state", "online"); 1488331766Sken } else { 1489331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_link_state", "offline"); 1490331766Sken } 1491331766Sken } 1492331766Sken} 1493331766Sken 1494331766Skenstatic void 1495331766Skenget_configured_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1496331766Sken{ 1497331766Sken ocs_xport_stats_t value; 1498331766Sken 1499331766Sken if (ocs_xport_status(ocs->xport, OCS_XPORT_CONFIG_PORT_STATUS, &value) == 0) { 1500331766Sken if (value.value == OCS_XPORT_PORT_ONLINE) { 1501331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_link_state", "online"); 1502331766Sken } else { 1503331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_link_state", "offline"); 1504331766Sken } 1505331766Sken } 1506331766Sken} 1507331766Sken 1508331766Sken/** 1509331766Sken * @brief HW link config enum to mgmt string value mapping. 1510331766Sken * 1511331766Sken * This structure provides a mapping from the ocs_hw_linkcfg_e 1512331766Sken * enum (enum exposed for the OCS_HW_PORT_SET_LINK_CONFIG port 1513331766Sken * control) to the mgmt string that is passed in by the mgmt application 1514331766Sken * (elxsdkutil). 1515331766Sken */ 1516331766Skentypedef struct ocs_mgmt_linkcfg_map_s { 1517331766Sken ocs_hw_linkcfg_e linkcfg; 1518331766Sken const char *mgmt_str; 1519331766Sken} ocs_mgmt_linkcfg_map_t; 1520331766Sken 1521331766Skenstatic ocs_mgmt_linkcfg_map_t mgmt_linkcfg_map[] = { 1522331766Sken {OCS_HW_LINKCFG_4X10G, OCS_CONFIG_LINKCFG_4X10G}, 1523331766Sken {OCS_HW_LINKCFG_1X40G, OCS_CONFIG_LINKCFG_1X40G}, 1524331766Sken {OCS_HW_LINKCFG_2X16G, OCS_CONFIG_LINKCFG_2X16G}, 1525331766Sken {OCS_HW_LINKCFG_4X8G, OCS_CONFIG_LINKCFG_4X8G}, 1526331766Sken {OCS_HW_LINKCFG_4X1G, OCS_CONFIG_LINKCFG_4X1G}, 1527331766Sken {OCS_HW_LINKCFG_2X10G, OCS_CONFIG_LINKCFG_2X10G}, 1528331766Sken {OCS_HW_LINKCFG_2X10G_2X8G, OCS_CONFIG_LINKCFG_2X10G_2X8G}}; 1529331766Sken 1530331766Sken/** 1531331766Sken * @brief Get the HW linkcfg enum from the mgmt config string. 1532331766Sken * 1533331766Sken * @param mgmt_str mgmt string value. 1534331766Sken * 1535331766Sken * @return Returns the HW linkcfg enum corresponding to clp_str. 1536331766Sken */ 1537331766Skenstatic ocs_hw_linkcfg_e 1538331766Skenocs_hw_linkcfg_from_mgmt(const char *mgmt_str) 1539331766Sken{ 1540331766Sken uint32_t i; 1541331766Sken for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) { 1542331766Sken if (ocs_strncmp(mgmt_linkcfg_map[i].mgmt_str, 1543331766Sken mgmt_str, ocs_strlen(mgmt_str)) == 0) { 1544331766Sken return mgmt_linkcfg_map[i].linkcfg; 1545331766Sken } 1546331766Sken } 1547331766Sken return OCS_HW_LINKCFG_NA; 1548331766Sken} 1549331766Sken 1550331766Sken/** 1551331766Sken * @brief Get the mgmt string value from the HW linkcfg enum. 1552331766Sken * 1553331766Sken * @param linkcfg HW linkcfg enum. 1554331766Sken * 1555331766Sken * @return Returns the mgmt string value corresponding to the given HW linkcfg. 1556331766Sken */ 1557331766Skenstatic const char * 1558331766Skenocs_mgmt_from_hw_linkcfg(ocs_hw_linkcfg_e linkcfg) 1559331766Sken{ 1560331766Sken uint32_t i; 1561331766Sken for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) { 1562331766Sken if (mgmt_linkcfg_map[i].linkcfg == linkcfg) { 1563331766Sken return mgmt_linkcfg_map[i].mgmt_str; 1564331766Sken } 1565331766Sken } 1566331766Sken return OCS_CONFIG_LINKCFG_UNKNOWN; 1567331766Sken} 1568331766Sken 1569331766Sken/** 1570331766Sken * @brief Link configuration callback argument 1571331766Sken */ 1572331766Skentypedef struct ocs_mgmt_linkcfg_arg_s { 1573331766Sken ocs_sem_t semaphore; 1574331766Sken int32_t status; 1575331766Sken ocs_hw_linkcfg_e linkcfg; 1576331766Sken} ocs_mgmt_linkcfg_arg_t; 1577331766Sken 1578331766Sken/** 1579331766Sken * @brief Get linkcfg config value 1580331766Sken * 1581331766Sken * @param ocs Pointer to the ocs structure. 1582331766Sken * @param name Not used. 1583331766Sken * @param textbuf The textbuf to which the result is written. 1584331766Sken * 1585331766Sken * @return None. 1586331766Sken */ 1587331766Skenstatic void 1588331766Skenget_linkcfg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1589331766Sken{ 1590331766Sken const char *linkcfg_str = NULL; 1591331766Sken uint32_t value; 1592331766Sken ocs_hw_linkcfg_e linkcfg; 1593331766Sken ocs_hw_get(&ocs->hw, OCS_HW_LINKCFG, &value); 1594331766Sken linkcfg = (ocs_hw_linkcfg_e)value; 1595331766Sken linkcfg_str = ocs_mgmt_from_hw_linkcfg(linkcfg); 1596331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "linkcfg", linkcfg_str); 1597331766Sken} 1598331766Sken 1599331766Sken/** 1600331766Sken * @brief Get requested WWNN config value 1601331766Sken * 1602331766Sken * @param ocs Pointer to the ocs structure. 1603331766Sken * @param name Not used. 1604331766Sken * @param textbuf The textbuf to which the result is written. 1605331766Sken * 1606331766Sken * @return None. 1607331766Sken */ 1608331766Skenstatic void 1609331766Skenget_req_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1610331766Sken{ 1611331766Sken ocs_xport_t *xport = ocs->xport; 1612331766Sken 1613331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "requested_wwnn", "0x%llx", (unsigned long long)xport->req_wwnn); 1614331766Sken} 1615331766Sken 1616331766Sken/** 1617331766Sken * @brief Get requested WWPN config value 1618331766Sken * 1619331766Sken * @param ocs Pointer to the ocs structure. 1620331766Sken * @param name Not used. 1621331766Sken * @param textbuf The textbuf to which the result is written. 1622331766Sken * 1623331766Sken * @return None. 1624331766Sken */ 1625331766Skenstatic void 1626331766Skenget_req_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1627331766Sken{ 1628331766Sken ocs_xport_t *xport = ocs->xport; 1629331766Sken 1630331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "requested_wwpn", "0x%llx", (unsigned long long)xport->req_wwpn); 1631331766Sken} 1632331766Sken 1633331766Sken/** 1634331766Sken * @brief Get requested nodedb_mask config value 1635331766Sken * 1636331766Sken * @param ocs Pointer to the ocs structure. 1637331766Sken * @param name Not used. 1638331766Sken * @param textbuf The textbuf to which the result is written. 1639331766Sken * 1640331766Sken * @return None. 1641331766Sken */ 1642331766Skenstatic void 1643331766Skenget_nodedb_mask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 1644331766Sken{ 1645331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "nodedb_mask", "0x%08x", ocs->nodedb_mask); 1646331766Sken} 1647331766Sken 1648331766Sken/** 1649331766Sken * @brief Set requested WWNN value. 1650331766Sken * 1651331766Sken * @param ocs Pointer to the ocs structure. 1652331766Sken * @param name Not used. 1653331766Sken * @param value Value to which the linkcfg is set. 1654331766Sken * 1655331766Sken * @return Returns 0 on success. 1656331766Sken */ 1657331766Sken 1658331766Skenint 1659331766Skenset_req_wwnn(ocs_t *ocs, char *name, char *value) 1660331766Sken{ 1661331766Sken int rc; 1662331766Sken uint64_t wwnn; 1663331766Sken 1664331766Sken if (ocs_strcasecmp(value, "default") == 0) { 1665331766Sken wwnn = 0; 1666331766Sken } 1667331766Sken else if (parse_wwn(value, &wwnn) != 0) { 1668331766Sken ocs_log_test(ocs, "Invalid WWNN: %s\n", value); 1669331766Sken return 1; 1670331766Sken } 1671331766Sken 1672331766Sken rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWNN_SET, wwnn); 1673331766Sken 1674331766Sken if(rc) { 1675331766Sken ocs_log_test(ocs, "OCS_XPORT_WWNN_SET failed: %d\n", rc); 1676331766Sken return rc; 1677331766Sken } 1678331766Sken 1679331766Sken rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE); 1680331766Sken if (rc) { 1681331766Sken ocs_log_test(ocs, "port offline failed : %d\n", rc); 1682331766Sken } 1683331766Sken 1684331766Sken rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); 1685331766Sken if (rc) { 1686331766Sken ocs_log_test(ocs, "port online failed : %d\n", rc); 1687331766Sken } 1688331766Sken 1689331766Sken return rc; 1690331766Sken} 1691331766Sken 1692331766Sken/** 1693331766Sken * @brief Set requested WWNP value. 1694331766Sken * 1695331766Sken * @param ocs Pointer to the ocs structure. 1696331766Sken * @param name Not used. 1697331766Sken * @param value Value to which the linkcfg is set. 1698331766Sken * 1699331766Sken * @return Returns 0 on success. 1700331766Sken */ 1701331766Sken 1702331766Skenint 1703331766Skenset_req_wwpn(ocs_t *ocs, char *name, char *value) 1704331766Sken{ 1705331766Sken int rc; 1706331766Sken uint64_t wwpn; 1707331766Sken 1708331766Sken if (ocs_strcasecmp(value, "default") == 0) { 1709331766Sken wwpn = 0; 1710331766Sken } 1711331766Sken else if (parse_wwn(value, &wwpn) != 0) { 1712331766Sken ocs_log_test(ocs, "Invalid WWPN: %s\n", value); 1713331766Sken return 1; 1714331766Sken } 1715331766Sken 1716331766Sken rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWPN_SET, wwpn); 1717331766Sken 1718331766Sken if(rc) { 1719331766Sken ocs_log_test(ocs, "OCS_XPORT_WWPN_SET failed: %d\n", rc); 1720331766Sken return rc; 1721331766Sken } 1722331766Sken 1723331766Sken rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE); 1724331766Sken if (rc) { 1725331766Sken ocs_log_test(ocs, "port offline failed : %d\n", rc); 1726331766Sken } 1727331766Sken 1728331766Sken rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); 1729331766Sken if (rc) { 1730331766Sken ocs_log_test(ocs, "port online failed : %d\n", rc); 1731331766Sken } 1732331766Sken 1733331766Sken return rc; 1734331766Sken} 1735331766Sken 1736331766Sken/** 1737331766Sken * @brief Set node debug mask value 1738331766Sken * 1739331766Sken * @param ocs Pointer to the ocs structure. 1740331766Sken * @param name Not used. 1741331766Sken * @param value Value to which the nodedb_mask is set. 1742331766Sken * 1743331766Sken * @return Returns 0 on success. 1744331766Sken */ 1745331766Skenstatic int 1746331766Skenset_nodedb_mask(ocs_t *ocs, char *name, char *value) 1747331766Sken{ 1748331766Sken ocs->nodedb_mask = ocs_strtoul(value, 0, 0); 1749331766Sken return 0; 1750331766Sken} 1751331766Sken 1752331766Sken/** 1753331766Sken * @brief Set linkcfg config value. 1754331766Sken * 1755331766Sken * @param ocs Pointer to the ocs structure. 1756331766Sken * @param name Not used. 1757331766Sken * @param value Value to which the linkcfg is set. 1758331766Sken * 1759331766Sken * @return Returns 0 on success. 1760331766Sken */ 1761331766Skenstatic int 1762331766Skenset_linkcfg(ocs_t *ocs, char *name, char *value) 1763331766Sken{ 1764331766Sken ocs_hw_linkcfg_e linkcfg; 1765331766Sken ocs_mgmt_linkcfg_arg_t cb_arg; 1766331766Sken ocs_hw_rtn_e status; 1767331766Sken 1768331766Sken ocs_sem_init(&cb_arg.semaphore, 0, "mgmt_linkcfg"); 1769331766Sken 1770331766Sken /* translate mgmt linkcfg string to HW linkcfg enum */ 1771331766Sken linkcfg = ocs_hw_linkcfg_from_mgmt(value); 1772331766Sken 1773331766Sken /* set HW linkcfg */ 1774331766Sken status = ocs_hw_port_control(&ocs->hw, OCS_HW_PORT_SET_LINK_CONFIG, 1775331766Sken (uintptr_t)linkcfg, ocs_mgmt_linkcfg_cb, &cb_arg); 1776331766Sken if (status) { 1777331766Sken ocs_log_test(ocs, "ocs_hw_set_linkcfg failed\n"); 1778331766Sken return -1; 1779331766Sken } 1780331766Sken 1781331766Sken if (ocs_sem_p(&cb_arg.semaphore, OCS_SEM_FOREVER)) { 1782331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 1783331766Sken return -1; 1784331766Sken } 1785331766Sken 1786331766Sken if (cb_arg.status) { 1787331766Sken ocs_log_test(ocs, "failed to set linkcfg from HW status=%d\n", 1788331766Sken cb_arg.status); 1789331766Sken return -1; 1790331766Sken } 1791331766Sken 1792331766Sken return 0; 1793331766Sken} 1794331766Sken 1795331766Sken/** 1796331766Sken * @brief Linkcfg callback 1797331766Sken * 1798331766Sken * @param status Result of the linkcfg get/set operation. 1799331766Sken * @param value Resulting linkcfg value. 1800331766Sken * @param arg Callback argument. 1801331766Sken * 1802331766Sken * @return None. 1803331766Sken */ 1804331766Skenstatic void 1805331766Skenocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg) 1806331766Sken{ 1807331766Sken ocs_mgmt_linkcfg_arg_t *cb_arg = (ocs_mgmt_linkcfg_arg_t *)arg; 1808331766Sken cb_arg->status = status; 1809331766Sken cb_arg->linkcfg = (ocs_hw_linkcfg_e)value; 1810331766Sken ocs_sem_v(&cb_arg->semaphore); 1811331766Sken} 1812331766Sken 1813331766Skenstatic int 1814331766Skenset_debug_mq_dump(ocs_t *ocs, char *name, char *value) 1815331766Sken{ 1816331766Sken int result; 1817331766Sken 1818331766Sken if (ocs_strcasecmp(value, "false") == 0) { 1819331766Sken ocs_debug_disable(OCS_DEBUG_ENABLE_MQ_DUMP); 1820331766Sken result = 0; 1821331766Sken } else if (ocs_strcasecmp(value, "true") == 0) { 1822331766Sken ocs_debug_enable(OCS_DEBUG_ENABLE_MQ_DUMP); 1823331766Sken result = 0; 1824331766Sken } else { 1825331766Sken result = -1; 1826331766Sken } 1827331766Sken 1828331766Sken return result; 1829331766Sken} 1830331766Sken 1831331766Skenstatic int 1832331766Skenset_debug_cq_dump(ocs_t *ocs, char *name, char *value) 1833331766Sken{ 1834331766Sken int result; 1835331766Sken 1836331766Sken if (ocs_strcasecmp(value, "false") == 0) { 1837331766Sken ocs_debug_disable(OCS_DEBUG_ENABLE_CQ_DUMP); 1838331766Sken result = 0; 1839331766Sken } else if (ocs_strcasecmp(value, "true") == 0) { 1840331766Sken ocs_debug_enable(OCS_DEBUG_ENABLE_CQ_DUMP); 1841331766Sken result = 0; 1842331766Sken } else { 1843331766Sken result = -1; 1844331766Sken } 1845331766Sken 1846331766Sken return result; 1847331766Sken} 1848331766Sken 1849331766Skenstatic int 1850331766Skenset_debug_wq_dump(ocs_t *ocs, char *name, char *value) 1851331766Sken{ 1852331766Sken int result; 1853331766Sken 1854331766Sken if (ocs_strcasecmp(value, "false") == 0) { 1855331766Sken ocs_debug_disable(OCS_DEBUG_ENABLE_WQ_DUMP); 1856331766Sken result = 0; 1857331766Sken } else if (ocs_strcasecmp(value, "true") == 0) { 1858331766Sken ocs_debug_enable(OCS_DEBUG_ENABLE_WQ_DUMP); 1859331766Sken result = 0; 1860331766Sken } else { 1861331766Sken result = -1; 1862331766Sken } 1863331766Sken 1864331766Sken return result; 1865331766Sken} 1866331766Sken 1867331766Skenstatic int 1868331766Skenset_debug_eq_dump(ocs_t *ocs, char *name, char *value) 1869331766Sken{ 1870331766Sken int result; 1871331766Sken 1872331766Sken if (ocs_strcasecmp(value, "false") == 0) { 1873331766Sken ocs_debug_disable(OCS_DEBUG_ENABLE_EQ_DUMP); 1874331766Sken result = 0; 1875331766Sken } else if (ocs_strcasecmp(value, "true") == 0) { 1876331766Sken ocs_debug_enable(OCS_DEBUG_ENABLE_EQ_DUMP); 1877331766Sken result = 0; 1878331766Sken } else { 1879331766Sken result = -1; 1880331766Sken } 1881331766Sken 1882331766Sken return result; 1883331766Sken} 1884331766Sken 1885331766Skenstatic int 1886331766Skenset_logmask(ocs_t *ocs, char *name, char *value) 1887331766Sken{ 1888331766Sken 1889331766Sken ocs->logmask = ocs_strtoul(value, NULL, 0); 1890331766Sken 1891331766Sken return 0; 1892331766Sken} 1893331766Sken 1894331766Skenstatic int 1895331766Skenset_loglevel(ocs_t *ocs, char *name, char *value) 1896331766Sken{ 1897331766Sken 1898331766Sken loglevel = ocs_strtoul(value, NULL, 0); 1899331766Sken 1900331766Sken return 0; 1901331766Sken} 1902331766Sken 1903331766Skenint 1904331766Skenset_configured_speed(ocs_t *ocs, char *name, char *value) 1905331766Sken{ 1906331766Sken int result = 0; 1907331766Sken ocs_hw_rtn_e hw_rc; 1908331766Sken int xport_rc; 1909331766Sken uint32_t spd; 1910331766Sken 1911331766Sken spd = ocs_strtoul(value, NULL, 0); 1912331766Sken 1913331766Sken if ((spd != 0) && (spd != 2000) && (spd != 4000) && 1914331766Sken (spd != 8000) && (spd != 16000) && (spd != 32000)) { 1915331766Sken ocs_log_test(ocs, "unsupported speed %d\n", spd); 1916331766Sken return 1; 1917331766Sken } 1918331766Sken 1919331766Sken ocs_log_debug(ocs, "Taking port offline\n"); 1920331766Sken xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE); 1921331766Sken if (xport_rc != 0) { 1922331766Sken ocs_log_test(ocs, "Port offline failed\n"); 1923331766Sken result = 1; 1924331766Sken } else { 1925331766Sken ocs_log_debug(ocs, "Setting port to speed %d\n", spd); 1926331766Sken hw_rc = ocs_hw_set(&ocs->hw, OCS_HW_LINK_SPEED, spd); 1927331766Sken if (hw_rc != OCS_HW_RTN_SUCCESS) { 1928331766Sken ocs_log_test(ocs, "Speed set failed\n"); 1929331766Sken result = 1; 1930331766Sken } 1931331766Sken 1932331766Sken /* If we failed to set the speed we still want to try to bring 1933331766Sken * the port back online */ 1934331766Sken 1935331766Sken ocs_log_debug(ocs, "Bringing port online\n"); 1936331766Sken xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); 1937331766Sken if (xport_rc != 0) { 1938331766Sken result = 1; 1939331766Sken } 1940331766Sken } 1941331766Sken 1942331766Sken return result; 1943331766Sken} 1944331766Sken 1945331766Skenint 1946331766Skenset_configured_topology(ocs_t *ocs, char *name, char *value) 1947331766Sken{ 1948331766Sken int result = 0; 1949331766Sken ocs_hw_rtn_e hw_rc; 1950331766Sken int xport_rc; 1951331766Sken uint32_t topo; 1952331766Sken 1953331766Sken topo = ocs_strtoul(value, NULL, 0); 1954331766Sken if (topo >= OCS_HW_TOPOLOGY_NONE) { 1955331766Sken return 1; 1956331766Sken } 1957331766Sken 1958331766Sken ocs_log_debug(ocs, "Taking port offline\n"); 1959331766Sken xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE); 1960331766Sken if (xport_rc != 0) { 1961331766Sken ocs_log_test(ocs, "Port offline failed\n"); 1962331766Sken result = 1; 1963331766Sken } else { 1964331766Sken ocs_log_debug(ocs, "Setting port to topology %d\n", topo); 1965331766Sken hw_rc = ocs_hw_set(&ocs->hw, OCS_HW_TOPOLOGY, topo); 1966331766Sken if (hw_rc != OCS_HW_RTN_SUCCESS) { 1967331766Sken ocs_log_test(ocs, "Topology set failed\n"); 1968331766Sken result = 1; 1969331766Sken } 1970331766Sken 1971331766Sken /* If we failed to set the topology we still want to try to bring 1972331766Sken * the port back online */ 1973331766Sken 1974331766Sken ocs_log_debug(ocs, "Bringing port online\n"); 1975331766Sken xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); 1976331766Sken if (xport_rc != 0) { 1977331766Sken result = 1; 1978331766Sken } 1979331766Sken } 1980331766Sken 1981331766Sken return result; 1982331766Sken} 1983331766Sken 1984331766Skenstatic int 1985331766Skenset_configured_link_state(ocs_t *ocs, char *name, char *value) 1986331766Sken{ 1987331766Sken int result = 0; 1988331766Sken int xport_rc; 1989331766Sken 1990331766Sken if (ocs_strcasecmp(value, "offline") == 0) { 1991331766Sken ocs_log_debug(ocs, "Setting port to %s\n", value); 1992331766Sken xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE); 1993331766Sken if (xport_rc != 0) { 1994331766Sken ocs_log_test(ocs, "Setting port to offline failed\n"); 1995331766Sken result = -1; 1996331766Sken } 1997331766Sken } else if (ocs_strcasecmp(value, "online") == 0) { 1998331766Sken ocs_log_debug(ocs, "Setting port to %s\n", value); 1999331766Sken xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE); 2000331766Sken if (xport_rc != 0) { 2001331766Sken ocs_log_test(ocs, "Setting port to online failed\n"); 2002331766Sken result = -1; 2003331766Sken } 2004331766Sken } else { 2005331766Sken ocs_log_test(ocs, "Unsupported link state \"%s\"\n", value); 2006331766Sken result = -1; 2007331766Sken } 2008331766Sken 2009331766Sken return result; 2010331766Sken} 2011331766Sken 2012331766Skentypedef struct ocs_mgmt_get_port_protocol_result { 2013331766Sken ocs_sem_t semaphore; 2014331766Sken int32_t status; 2015331766Sken ocs_hw_port_protocol_e port_protocol; 2016331766Sken} ocs_mgmt_get_port_protocol_result_t; 2017331766Sken 2018331766Sken 2019331766Skenstatic void 2020331766Skenocs_mgmt_get_port_protocol_cb(int32_t status, 2021331766Sken ocs_hw_port_protocol_e port_protocol, 2022331766Sken void *arg) 2023331766Sken{ 2024331766Sken ocs_mgmt_get_port_protocol_result_t *result = arg; 2025331766Sken 2026331766Sken result->status = status; 2027331766Sken result->port_protocol = port_protocol; 2028331766Sken 2029331766Sken ocs_sem_v(&(result->semaphore)); 2030331766Sken} 2031331766Sken 2032331766Skenstatic void 2033331766Skenget_port_protocol(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 2034331766Sken{ 2035331766Sken ocs_mgmt_get_port_protocol_result_t result; 2036331766Sken uint8_t bus; 2037331766Sken uint8_t dev; 2038331766Sken uint8_t func; 2039331766Sken 2040331766Sken ocs_sem_init(&(result.semaphore), 0, "get_port_protocol"); 2041331766Sken 2042331766Sken ocs_get_bus_dev_func(ocs, &bus, &dev, &func); 2043331766Sken 2044331766Sken if(ocs_hw_get_port_protocol(&ocs->hw, func, ocs_mgmt_get_port_protocol_cb, &result) == OCS_HW_RTN_SUCCESS) { 2045331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2046331766Sken /* Undefined failure */ 2047331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2048331766Sken } 2049331766Sken if (result.status == 0) { 2050331766Sken switch (result.port_protocol) { 2051331766Sken case OCS_HW_PORT_PROTOCOL_ISCSI: 2052331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "iSCSI"); 2053331766Sken break; 2054331766Sken case OCS_HW_PORT_PROTOCOL_FCOE: 2055331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FCoE"); 2056331766Sken break; 2057331766Sken case OCS_HW_PORT_PROTOCOL_FC: 2058331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FC"); 2059331766Sken break; 2060331766Sken case OCS_HW_PORT_PROTOCOL_OTHER: 2061331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Other"); 2062331766Sken break; 2063331766Sken } 2064331766Sken } else { 2065331766Sken ocs_log_test(ocs, "getting port profile status 0x%x\n", result.status); 2066331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Unknown"); 2067331766Sken } 2068331766Sken } 2069331766Sken} 2070331766Sken 2071331766Skentypedef struct ocs_mgmt_set_port_protocol_result { 2072331766Sken ocs_sem_t semaphore; 2073331766Sken int32_t status; 2074331766Sken} ocs_mgmt_set_port_protocol_result_t; 2075331766Sken 2076331766Sken 2077331766Sken 2078331766Skenstatic void 2079331766Skenocs_mgmt_set_port_protocol_cb(int32_t status, 2080331766Sken void *arg) 2081331766Sken{ 2082331766Sken ocs_mgmt_get_port_protocol_result_t *result = arg; 2083331766Sken 2084331766Sken result->status = status; 2085331766Sken 2086331766Sken ocs_sem_v(&(result->semaphore)); 2087331766Sken} 2088331766Sken 2089331766Sken/** 2090331766Sken * @brief Set port protocol 2091331766Sken * @par Description 2092331766Sken * This is a management action handler to set the current 2093331766Sken * port protocol. Input value should be one of iSCSI, 2094331766Sken * FC, or FCoE. 2095331766Sken * 2096331766Sken * @param ocs Pointer to the ocs structure. 2097331766Sken * @param name Name of the action being performed. 2098331766Sken * @param value The value to be assigned 2099331766Sken * 2100331766Sken * @return Returns 0 on success, non-zero on failure. 2101331766Sken */ 2102331766Skenstatic int32_t 2103331766Skenset_port_protocol(ocs_t *ocs, char *name, char *value) 2104331766Sken{ 2105331766Sken ocs_mgmt_set_port_protocol_result_t result; 2106331766Sken int32_t rc = 0; 2107331766Sken ocs_hw_port_protocol_e new_protocol; 2108331766Sken uint8_t bus; 2109331766Sken uint8_t dev; 2110331766Sken uint8_t func; 2111331766Sken 2112331766Sken ocs_get_bus_dev_func(ocs, &bus, &dev, &func); 2113331766Sken 2114331766Sken ocs_sem_init(&(result.semaphore), 0, "set_port_protocol"); 2115331766Sken 2116331766Sken if (ocs_strcasecmp(value, "iscsi") == 0) { 2117331766Sken new_protocol = OCS_HW_PORT_PROTOCOL_ISCSI; 2118331766Sken } else if (ocs_strcasecmp(value, "fc") == 0) { 2119331766Sken new_protocol = OCS_HW_PORT_PROTOCOL_FC; 2120331766Sken } else if (ocs_strcasecmp(value, "fcoe") == 0) { 2121331766Sken new_protocol = OCS_HW_PORT_PROTOCOL_FCOE; 2122331766Sken } else { 2123331766Sken return -1; 2124331766Sken } 2125331766Sken 2126331766Sken rc = ocs_hw_set_port_protocol(&ocs->hw, new_protocol, func, 2127331766Sken ocs_mgmt_set_port_protocol_cb, &result); 2128331766Sken if (rc == OCS_HW_RTN_SUCCESS) { 2129331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2130331766Sken /* Undefined failure */ 2131331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2132331766Sken rc = -ENXIO; 2133331766Sken } 2134331766Sken if (result.status == 0) { 2135331766Sken /* Success. */ 2136331766Sken rc = 0; 2137331766Sken } else { 2138331766Sken rc = -1; 2139331766Sken ocs_log_test(ocs, "setting active profile status 0x%x\n", 2140331766Sken result.status); 2141331766Sken } 2142331766Sken } 2143331766Sken 2144331766Sken return rc; 2145331766Sken} 2146331766Sken 2147331766Skentypedef struct ocs_mgmt_get_profile_list_result_s { 2148331766Sken ocs_sem_t semaphore; 2149331766Sken int32_t status; 2150331766Sken ocs_hw_profile_list_t *list; 2151331766Sken} ocs_mgmt_get_profile_list_result_t; 2152331766Sken 2153331766Skenstatic void 2154331766Skenocs_mgmt_get_profile_list_cb(int32_t status, ocs_hw_profile_list_t *list, void *ul_arg) 2155331766Sken{ 2156331766Sken ocs_mgmt_get_profile_list_result_t *result = ul_arg; 2157331766Sken 2158331766Sken result->status = status; 2159331766Sken result->list = list; 2160331766Sken 2161331766Sken ocs_sem_v(&(result->semaphore)); 2162331766Sken} 2163331766Sken 2164331766Sken/** 2165331766Sken * @brief Get list of profiles 2166331766Sken * @par Description 2167331766Sken * This is a management action handler to get the list of 2168331766Sken * profiles supported by the SLI port. Although the spec says 2169331766Sken * that all SLI platforms support this, only Skyhawk actually 2170331766Sken * has a useful implementation. 2171331766Sken * 2172331766Sken * @param ocs Pointer to the ocs structure. 2173331766Sken * @param name Name of the action being performed. 2174331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to return the results. 2175331766Sken * 2176331766Sken * @return none 2177331766Sken */ 2178331766Skenstatic void 2179331766Skenget_profile_list(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 2180331766Sken{ 2181331766Sken ocs_mgmt_get_profile_list_result_t result; 2182331766Sken 2183331766Sken ocs_sem_init(&(result.semaphore), 0, "get_profile_list"); 2184331766Sken 2185331766Sken if(ocs_hw_get_profile_list(&ocs->hw, ocs_mgmt_get_profile_list_cb, &result) == OCS_HW_RTN_SUCCESS) { 2186331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2187331766Sken /* Undefined failure */ 2188331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2189331766Sken } 2190331766Sken if (result.status == 0) { 2191331766Sken /* Success. */ 2192331766Sken#define MAX_LINE_SIZE 520 2193331766Sken#define BUFFER_SIZE MAX_LINE_SIZE*40 2194331766Sken char *result_buf; 2195331766Sken char result_line[MAX_LINE_SIZE]; 2196331766Sken uint32_t bytes_left; 2197331766Sken uint32_t i; 2198331766Sken 2199331766Sken result_buf = ocs_malloc(ocs, BUFFER_SIZE, OCS_M_ZERO); 2200331766Sken bytes_left = BUFFER_SIZE; 2201331766Sken 2202331766Sken for (i=0; i<result.list->num_descriptors; i++) { 2203331766Sken sprintf(result_line, "0x%02x:%s\n", result.list->descriptors[i].profile_id, 2204331766Sken result.list->descriptors[i].profile_description); 2205331766Sken if (strlen(result_line) < bytes_left) { 2206331766Sken strcat(result_buf, result_line); 2207331766Sken bytes_left -= strlen(result_line); 2208331766Sken } 2209331766Sken } 2210331766Sken 2211331766Sken 2212331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "profile_list", result_buf); 2213331766Sken 2214331766Sken ocs_free(ocs, result_buf, BUFFER_SIZE); 2215331766Sken ocs_free(ocs, result.list, sizeof(ocs_hw_profile_list_t)); 2216331766Sken } else { 2217331766Sken ocs_log_test(ocs, "getting profile list status 0x%x\n", result.status); 2218331766Sken } 2219331766Sken } 2220331766Sken} 2221331766Sken 2222331766Skentypedef struct ocs_mgmt_get_active_profile_result { 2223331766Sken ocs_sem_t semaphore; 2224331766Sken int32_t status; 2225331766Sken uint32_t active_profile_id; 2226331766Sken} ocs_mgmt_get_active_profile_result_t; 2227331766Sken 2228331766Skenstatic void 2229331766Skenocs_mgmt_get_active_profile_cb(int32_t status, uint32_t active_profile, void *ul_arg) 2230331766Sken{ 2231331766Sken ocs_mgmt_get_active_profile_result_t *result = ul_arg; 2232331766Sken 2233331766Sken result->status = status; 2234331766Sken result->active_profile_id = active_profile; 2235331766Sken 2236331766Sken ocs_sem_v(&(result->semaphore)); 2237331766Sken} 2238331766Sken 2239331766Sken#define MAX_PROFILE_LENGTH 5 2240331766Sken 2241331766Sken/** 2242331766Sken * @brief Get active profile 2243331766Sken * @par Description 2244331766Sken * This is a management action handler to get the currently 2245331766Sken * active profile for an SLI port. Although the spec says that 2246331766Sken * all SLI platforms support this, only Skyhawk actually has a 2247331766Sken * useful implementation. 2248331766Sken * 2249331766Sken * @param ocs Pointer to the ocs structure. 2250331766Sken * @param name Name of the action being performed. 2251331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to return the results. 2252331766Sken * 2253331766Sken * @return none 2254331766Sken */ 2255331766Skenstatic void 2256331766Skenget_active_profile(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 2257331766Sken{ 2258331766Sken char result_string[MAX_PROFILE_LENGTH]; 2259331766Sken ocs_mgmt_get_active_profile_result_t result; 2260331766Sken 2261331766Sken ocs_sem_init(&(result.semaphore), 0, "get_active_profile"); 2262331766Sken 2263331766Sken if(ocs_hw_get_active_profile(&ocs->hw, ocs_mgmt_get_active_profile_cb, &result) == OCS_HW_RTN_SUCCESS) { 2264331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2265331766Sken /* Undefined failure */ 2266331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2267331766Sken } 2268331766Sken if (result.status == 0) { 2269331766Sken /* Success. */ 2270331766Sken sprintf(result_string, "0x%02x", result.active_profile_id); 2271331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "active_profile", result_string); 2272331766Sken } else { 2273331766Sken ocs_log_test(ocs, "getting active profile status 0x%x\n", result.status); 2274331766Sken } 2275331766Sken } 2276331766Sken} 2277331766Sken 2278331766Skentypedef struct ocs_mgmt_set_active_profile_result { 2279331766Sken ocs_sem_t semaphore; 2280331766Sken int32_t status; 2281331766Sken} ocs_mgmt_set_active_profile_result_t; 2282331766Sken 2283331766Sken 2284331766Skenstatic void 2285331766Skenocs_mgmt_set_active_profile_cb(int32_t status, void *ul_arg) 2286331766Sken{ 2287331766Sken ocs_mgmt_get_profile_list_result_t *result = ul_arg; 2288331766Sken 2289331766Sken result->status = status; 2290331766Sken 2291331766Sken ocs_sem_v(&(result->semaphore)); 2292331766Sken} 2293331766Sken 2294331766Sken/** 2295331766Sken * @brief Set active profile 2296331766Sken * @par Description 2297331766Sken * This is a management action handler to set the currently 2298331766Sken * active profile for an SLI port. Although the spec says that 2299331766Sken * all SLI platforms support this, only Skyhawk actually has a 2300331766Sken * useful implementation. 2301331766Sken * 2302331766Sken * @param ocs Pointer to the ocs structure. 2303331766Sken * @param name Name of the action being performed. 2304331766Sken * @param value Requested new value of the property. 2305331766Sken * 2306331766Sken * @return Returns 0 on success, non-zero on failure. 2307331766Sken */ 2308331766Skenstatic int32_t 2309331766Skenset_active_profile(ocs_t *ocs, char *name, char *value) 2310331766Sken{ 2311331766Sken ocs_mgmt_set_active_profile_result_t result; 2312331766Sken int32_t rc = 0; 2313331766Sken int32_t new_profile; 2314331766Sken 2315331766Sken new_profile = ocs_strtoul(value, NULL, 0); 2316331766Sken 2317331766Sken ocs_sem_init(&(result.semaphore), 0, "set_active_profile"); 2318331766Sken 2319331766Sken rc = ocs_hw_set_active_profile(&ocs->hw, ocs_mgmt_set_active_profile_cb, new_profile, &result); 2320331766Sken if (rc == OCS_HW_RTN_SUCCESS) { 2321331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2322331766Sken /* Undefined failure */ 2323331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2324331766Sken rc = -ENXIO; 2325331766Sken } 2326331766Sken if (result.status == 0) { 2327331766Sken /* Success. */ 2328331766Sken rc = 0; 2329331766Sken } else { 2330331766Sken rc = -1; 2331331766Sken ocs_log_test(ocs, "setting active profile status 0x%x\n", result.status); 2332331766Sken } 2333331766Sken } 2334331766Sken 2335331766Sken return rc; 2336331766Sken} 2337331766Sken 2338331766Skentypedef struct ocs_mgmt_get_nvparms_result { 2339331766Sken ocs_sem_t semaphore; 2340331766Sken int32_t status; 2341331766Sken uint8_t wwpn[8]; 2342331766Sken uint8_t wwnn[8]; 2343331766Sken uint8_t hard_alpa; 2344331766Sken uint32_t preferred_d_id; 2345331766Sken} ocs_mgmt_get_nvparms_result_t; 2346331766Sken 2347331766Skenstatic void 2348331766Skenocs_mgmt_get_nvparms_cb(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa, 2349331766Sken uint32_t preferred_d_id, void *ul_arg) 2350331766Sken{ 2351331766Sken ocs_mgmt_get_nvparms_result_t *result = ul_arg; 2352331766Sken 2353331766Sken result->status = status; 2354331766Sken ocs_memcpy(result->wwpn, wwpn, sizeof(result->wwpn)); 2355331766Sken ocs_memcpy(result->wwnn, wwnn, sizeof(result->wwnn)); 2356331766Sken result->hard_alpa = hard_alpa; 2357331766Sken result->preferred_d_id = preferred_d_id; 2358331766Sken 2359331766Sken ocs_sem_v(&(result->semaphore)); 2360331766Sken} 2361331766Sken 2362331766Sken/** 2363331766Sken * @brief Get wwpn 2364331766Sken * @par Description 2365331766Sken * 2366331766Sken * 2367331766Sken * @param ocs Pointer to the ocs structure. 2368331766Sken * @param name Name of the action being performed. 2369331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to return the results. 2370331766Sken * 2371331766Sken * @return none 2372331766Sken */ 2373331766Skenstatic void 2374331766Skenget_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 2375331766Sken{ 2376331766Sken char result_string[24]; 2377334872Sram ocs_mgmt_get_nvparms_result_t result; 2378331766Sken 2379331766Sken ocs_sem_init(&(result.semaphore), 0, "get_nv_wwpn"); 2380331766Sken 2381331766Sken if(ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result) == OCS_HW_RTN_SUCCESS) { 2382331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2383331766Sken /* Undefined failure */ 2384331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2385331766Sken return; 2386331766Sken } 2387331766Sken if (result.status == 0) { 2388331766Sken /* Success. Copy wwpn from result struct to result string */ 2389331766Sken sprintf(result_string, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 2390331766Sken result.wwpn[0], result.wwpn[1], result.wwpn[2], 2391331766Sken result.wwpn[3], result.wwpn[4], result.wwpn[5], 2392331766Sken result.wwpn[6], result.wwpn[7]); 2393331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "nv_wwpn", result_string); 2394331766Sken } else { 2395331766Sken ocs_log_test(ocs, "getting wwpn status 0x%x\n", result.status); 2396331766Sken } 2397331766Sken } 2398331766Sken} 2399331766Sken 2400331766Sken/** 2401331766Sken * @brief Get wwnn 2402331766Sken * @par Description 2403331766Sken * 2404331766Sken * 2405331766Sken * @param ocs Pointer to the ocs structure. 2406331766Sken * @param name Name of the action being performed. 2407331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to return the results. 2408331766Sken * 2409331766Sken * @return none 2410331766Sken */ 2411331766Skenstatic void 2412331766Skenget_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 2413331766Sken{ 2414331766Sken char result_string[24]; 2415334872Sram ocs_mgmt_get_nvparms_result_t result; 2416331766Sken 2417331766Sken ocs_sem_init(&(result.semaphore), 0, "get_nv_wwnn"); 2418331766Sken 2419331766Sken if(ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result) == OCS_HW_RTN_SUCCESS) { 2420331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2421331766Sken /* Undefined failure */ 2422331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2423331766Sken return; 2424331766Sken } 2425331766Sken if (result.status == 0) { 2426331766Sken /* Success. Copy wwnn from result struct to result string */ 2427331766Sken ocs_snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 2428331766Sken result.wwnn[0], result.wwnn[1], result.wwnn[2], 2429331766Sken result.wwnn[3], result.wwnn[4], result.wwnn[5], 2430331766Sken result.wwnn[6], result.wwnn[7]); 2431331766Sken ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "nv_wwnn", result_string); 2432331766Sken } else { 2433331766Sken ocs_log_test(ocs, "getting wwnn status 0x%x\n", result.status); 2434331766Sken } 2435331766Sken } 2436331766Sken} 2437331766Sken 2438331766Sken/** 2439331766Sken * @brief Get accumulated node abort counts 2440331766Sken * @par Description Get the sum of all nodes abort count. 2441331766Sken * 2442331766Sken * @param ocs Pointer to the ocs structure. 2443331766Sken * @param name Name of the action being performed. 2444331766Sken * @param textbuf Pointer to an ocs_textbuf, which is used to return the results. 2445331766Sken * 2446331766Sken * @return None. 2447331766Sken */ 2448331766Skenstatic void 2449331766Skenget_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf) 2450331766Sken{ 2451331766Sken uint32_t abort_counts = 0; 2452331766Sken ocs_domain_t *domain; 2453331766Sken ocs_sport_t *sport; 2454331766Sken ocs_node_t *node; 2455331766Sken 2456331766Sken if (ocs_device_lock_try(ocs) != TRUE) { 2457331766Sken /* Didn't get the lock */ 2458331766Sken return; 2459331766Sken } 2460331766Sken 2461331766Sken /* Here the Device lock is held */ 2462331766Sken ocs_list_foreach(&ocs->domain_list, domain) { 2463331766Sken if (ocs_domain_lock_try(domain) != TRUE) { 2464331766Sken /* Didn't get the lock */ 2465331766Sken ocs_device_unlock(ocs); 2466331766Sken return; 2467331766Sken } 2468331766Sken 2469331766Sken /* Here the Domain lock is held */ 2470331766Sken ocs_list_foreach(&domain->sport_list, sport) { 2471331766Sken if (ocs_sport_lock_try(sport) != TRUE) { 2472331766Sken /* Didn't get the lock */ 2473331766Sken ocs_domain_unlock(domain); 2474331766Sken ocs_device_unlock(ocs); 2475331766Sken return; 2476331766Sken } 2477331766Sken 2478331766Sken /* Here the sport lock is held */ 2479331766Sken ocs_list_foreach(&sport->node_list, node) { 2480331766Sken abort_counts += node->abort_cnt; 2481331766Sken } 2482331766Sken 2483331766Sken ocs_sport_unlock(sport); 2484331766Sken } 2485331766Sken 2486331766Sken ocs_domain_unlock(domain); 2487331766Sken } 2488331766Sken 2489331766Sken ocs_device_unlock(ocs); 2490331766Sken 2491331766Sken ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "node_abort_cnt", "%d" , abort_counts); 2492331766Sken} 2493331766Sken 2494331766Skentypedef struct ocs_mgmt_set_nvparms_result { 2495331766Sken ocs_sem_t semaphore; 2496331766Sken int32_t status; 2497331766Sken} ocs_mgmt_set_nvparms_result_t; 2498331766Sken 2499331766Sken 2500331766Skenstatic void 2501331766Skenocs_mgmt_set_nvparms_cb(int32_t status, void *ul_arg) 2502331766Sken{ 2503331766Sken ocs_mgmt_get_profile_list_result_t *result = ul_arg; 2504331766Sken 2505331766Sken result->status = status; 2506331766Sken 2507331766Sken ocs_sem_v(&(result->semaphore)); 2508331766Sken} 2509331766Sken 2510331766Sken/** 2511331766Sken * @brief Set wwn 2512331766Sken * @par Description Sets the Non-volatile worldwide names, 2513331766Sken * if provided. 2514331766Sken * 2515331766Sken * @param ocs Pointer to the ocs structure. 2516331766Sken * @param name Name of the action being performed. 2517331766Sken * @param wwn_p Requested new WWN values. 2518331766Sken * 2519331766Sken * @return Returns 0 on success, non-zero on failure. 2520331766Sken */ 2521331766Skenstatic int32_t 2522331766Skenset_nv_wwn(ocs_t *ocs, char *name, char *wwn_p) 2523331766Sken{ 2524331766Sken ocs_mgmt_get_nvparms_result_t result; 2525331766Sken uint8_t new_wwpn[8]; 2526331766Sken uint8_t new_wwnn[8]; 2527331766Sken char *wwpn_p = NULL; 2528331766Sken char *wwnn_p = NULL; 2529331766Sken int32_t rc = -1; 2530331766Sken int wwpn; 2531331766Sken int wwnn; 2532331766Sken int i; 2533331766Sken 2534331766Sken /* This is a read-modify-write operation, so first we have to read 2535331766Sken * the current values 2536331766Sken */ 2537331766Sken ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn1"); 2538331766Sken 2539331766Sken rc = ocs_hw_get_nvparms(&ocs->hw, ocs_mgmt_get_nvparms_cb, &result); 2540331766Sken 2541331766Sken if (rc == OCS_HW_RTN_SUCCESS) { 2542331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2543331766Sken /* Undefined failure */ 2544331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2545331766Sken return -ENXIO; 2546331766Sken } 2547331766Sken if (result.status != 0) { 2548331766Sken ocs_log_test(ocs, "getting nvparms status 0x%x\n", result.status); 2549331766Sken return -1; 2550331766Sken } 2551331766Sken } 2552331766Sken 2553331766Sken /* wwn_p contains wwpn_p@wwnn_p values */ 2554331766Sken if (wwn_p != NULL) { 2555331766Sken wwpn_p = ocs_strsep(&wwn_p, "@"); 2556331766Sken wwnn_p = wwn_p; 2557331766Sken } 2558331766Sken 2559331766Sken wwpn = ocs_strcmp(wwpn_p, "NA"); 2560331766Sken wwnn = ocs_strcmp(wwnn_p, "NA"); 2561331766Sken 2562331766Sken /* Parse the new WWPN */ 2563331766Sken if ((wwpn_p != NULL) && (wwpn != 0)) { 2564331766Sken if (ocs_sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", 2565331766Sken &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]), 2566331766Sken &(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]), 2567331766Sken &(new_wwpn[6]), &(new_wwpn[7])) != 8) { 2568331766Sken ocs_log_test(ocs, "can't parse WWPN %s\n", wwpn_p); 2569331766Sken return -1; 2570331766Sken } 2571331766Sken } 2572331766Sken 2573331766Sken /* Parse the new WWNN */ 2574331766Sken if ((wwnn_p != NULL) && (wwnn != 0 )) { 2575331766Sken if (ocs_sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx", 2576331766Sken &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]), 2577331766Sken &(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]), 2578331766Sken &(new_wwnn[6]), &(new_wwnn[7])) != 8) { 2579331766Sken ocs_log_test(ocs, "can't parse WWNN %s\n", wwnn_p); 2580331766Sken return -1; 2581331766Sken } 2582331766Sken } 2583331766Sken 2584331766Sken for (i = 0; i < 8; i++) { 2585331766Sken /* Use active wwpn, if new one is not provided */ 2586331766Sken if (wwpn == 0) { 2587331766Sken new_wwpn[i] = result.wwpn[i]; 2588331766Sken } 2589331766Sken 2590331766Sken /* Use active wwnn, if new one is not provided */ 2591331766Sken if (wwnn == 0) { 2592331766Sken new_wwnn[i] = result.wwnn[i]; 2593331766Sken } 2594331766Sken } 2595331766Sken 2596331766Sken /* Modify the nv_wwnn and nv_wwpn, then write it back */ 2597331766Sken ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn2"); 2598331766Sken 2599331766Sken rc = ocs_hw_set_nvparms(&ocs->hw, ocs_mgmt_set_nvparms_cb, new_wwpn, 2600331766Sken new_wwnn, result.hard_alpa, result.preferred_d_id, 2601331766Sken &result); 2602331766Sken if (rc == OCS_HW_RTN_SUCCESS) { 2603331766Sken if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) { 2604331766Sken /* Undefined failure */ 2605331766Sken ocs_log_err(ocs, "ocs_sem_p failed\n"); 2606331766Sken return -ENXIO; 2607331766Sken } 2608331766Sken if (result.status != 0) { 2609331766Sken ocs_log_test(ocs, "setting wwn status 0x%x\n", result.status); 2610331766Sken return -1; 2611331766Sken } 2612331766Sken } 2613331766Sken 2614331766Sken return rc; 2615331766Sken} 2616331766Sken 2617331766Skenstatic int 2618331766Skenset_tgt_rscn_delay(ocs_t *ocs, char *name, char *value) 2619331766Sken{ 2620331766Sken ocs->tgt_rscn_delay_msec = ocs_strtoul(value, NULL, 0) * 1000; 2621331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2622331766Sken return 0; 2623331766Sken} 2624331766Sken 2625331766Skenstatic int 2626331766Skenset_tgt_rscn_period(ocs_t *ocs, char *name, char *value) 2627331766Sken{ 2628331766Sken ocs->tgt_rscn_period_msec = ocs_strtoul(value, NULL, 0) * 1000; 2629331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2630331766Sken return 0; 2631331766Sken} 2632331766Sken 2633331766Skenstatic int 2634331766Skenset_inject_drop_cmd(ocs_t *ocs, char *name, char *value) 2635331766Sken{ 2636331766Sken ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_CMD); 2637331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2638331766Sken return 0; 2639331766Sken} 2640331766Sken 2641331766Skenstatic int 2642331766Skenset_inject_free_drop_cmd(ocs_t *ocs, char *name, char *value) 2643331766Sken{ 2644331766Sken ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_FREE_DROPPED); 2645331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2646331766Sken return 0; 2647331766Sken} 2648331766Sken 2649331766Skenstatic int 2650331766Skenset_inject_drop_data(ocs_t *ocs, char *name, char *value) 2651331766Sken{ 2652331766Sken ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_DATA); 2653331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2654331766Sken return 0; 2655331766Sken} 2656331766Sken 2657331766Skenstatic int 2658331766Skenset_inject_drop_resp(ocs_t *ocs, char *name, char *value) 2659331766Sken{ 2660331766Sken ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_RESP); 2661331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2662331766Sken return 0; 2663331766Sken} 2664331766Sken 2665331766Skenstatic int 2666331766Skenset_cmd_err_inject(ocs_t *ocs, char *name, char *value) 2667331766Sken{ 2668331766Sken ocs->cmd_err_inject = ocs_strtoul(value, NULL, 0); 2669331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2670331766Sken return 0; 2671331766Sken} 2672331766Sken 2673331766Skenstatic int 2674331766Skenset_cmd_delay_value(ocs_t *ocs, char *name, char *value) 2675331766Sken{ 2676331766Sken ocs->delay_value_msec = ocs_strtoul(value, NULL, 0); 2677331766Sken ocs->err_injection = (ocs->delay_value_msec == 0 ? NO_ERR_INJECT : INJECT_DELAY_CMD); 2678331766Sken ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value); 2679331766Sken return 0; 2680331766Sken} 2681331766Sken 2682331766Sken/** 2683331766Sken * @brief parse a WWN from a string into a 64-bit value 2684331766Sken * 2685331766Sken * Given a pointer to a string, parse the string into a 64-bit 2686331766Sken * WWN value. The format of the string must be xx:xx:xx:xx:xx:xx:xx:xx 2687331766Sken * 2688331766Sken * @param wwn_in pointer to the string to be parsed 2689331766Sken * @param wwn_out pointer to uint64_t in which to put the parsed result 2690331766Sken * 2691331766Sken * @return 0 if successful, non-zero if the WWN is malformed and couldn't be parsed 2692331766Sken */ 2693331766Skenint 2694331766Skenparse_wwn(char *wwn_in, uint64_t *wwn_out) 2695331766Sken{ 2696331766Sken uint8_t byte0; 2697331766Sken uint8_t byte1; 2698331766Sken uint8_t byte2; 2699331766Sken uint8_t byte3; 2700331766Sken uint8_t byte4; 2701331766Sken uint8_t byte5; 2702331766Sken uint8_t byte6; 2703331766Sken uint8_t byte7; 2704331766Sken int rc; 2705331766Sken 2706331766Sken rc = ocs_sscanf(wwn_in, "0x%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", 2707331766Sken &byte0, &byte1, &byte2, &byte3, 2708331766Sken &byte4, &byte5, &byte6, &byte7); 2709331766Sken 2710331766Sken if (rc == 8) { 2711331766Sken *wwn_out = ((uint64_t)byte0 << 56) | 2712331766Sken ((uint64_t)byte1 << 48) | 2713331766Sken ((uint64_t)byte2 << 40) | 2714331766Sken ((uint64_t)byte3 << 32) | 2715331766Sken ((uint64_t)byte4 << 24) | 2716331766Sken ((uint64_t)byte5 << 16) | 2717331766Sken ((uint64_t)byte6 << 8) | 2718331766Sken ((uint64_t)byte7); 2719331766Sken return 0; 2720331766Sken 2721331766Sken } else { 2722331766Sken return 1; 2723331766Sken } 2724331766Sken} 2725331766Sken 2726331766Sken 2727331766Sken 2728331766Skenstatic char *mode_string(int mode); 2729331766Sken 2730331766Sken 2731331766Sken/** 2732331766Sken * @ingroup mgmt 2733331766Sken * @brief Generate the beginning of a numbered section in a management XML document. 2734331766Sken * 2735331766Sken * @par Description 2736331766Sken * This function begins a section. The XML information is appended to 2737331766Sken * the textbuf. This form of the function is used for sections that might have 2738331766Sken * multiple instances, such as a node or a SLI Port (sport). The index number 2739331766Sken * is appended to the name. 2740331766Sken * 2741331766Sken * @param textbuf Pointer to the driver dump text buffer. 2742331766Sken * @param name Name of the section. 2743331766Sken * @param index Index number of this instance of the section. 2744331766Sken * 2745331766Sken * @return None. 2746331766Sken */ 2747331766Sken 2748331766Skenextern void ocs_mgmt_start_section(ocs_textbuf_t *textbuf, const char *name, int index) 2749331766Sken{ 2750331766Sken ocs_textbuf_printf(textbuf, "<%s instance=\"%d\">\n", name, index); 2751331766Sken} 2752331766Sken 2753331766Sken/** 2754331766Sken * @ingroup mgmt 2755331766Sken * @brief Generate the beginning of an unnumbered section in a management XML document. 2756331766Sken * 2757331766Sken * @par Description 2758331766Sken * This function begins a section. The XML information is appended to 2759331766Sken * the textbuf. This form of the function is used for sections that have 2760331766Sken * a single instance only. Therefore, no index number is needed. 2761331766Sken * 2762331766Sken * @param textbuf Pointer to the driver dump text buffer. 2763331766Sken * @param name Name of the section. 2764331766Sken * 2765331766Sken * @return None. 2766331766Sken */ 2767331766Sken 2768331766Skenextern void ocs_mgmt_start_unnumbered_section(ocs_textbuf_t *textbuf, const char *name) 2769331766Sken{ 2770331766Sken ocs_textbuf_printf(textbuf, "<%s>\n", name); 2771331766Sken} 2772331766Sken 2773331766Sken/** 2774331766Sken * @ingroup mgmt 2775331766Sken * @brief Generate the end of a section in a management XML document. 2776331766Sken * 2777331766Sken * @par Description 2778331766Sken * This function ends a section. The XML information is appended to 2779331766Sken * the textbuf. 2780331766Sken * 2781331766Sken * @param textbuf Pointer to the driver dump text buffer. 2782331766Sken * @param name Name of the section. 2783331766Sken * 2784331766Sken * @return None. 2785331766Sken */ 2786331766Sken 2787331766Skenvoid ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name) 2788331766Sken{ 2789331766Sken ocs_textbuf_printf(textbuf, "</%s>\n", name); 2790331766Sken} 2791331766Sken 2792331766Sken/** 2793331766Sken * @ingroup mgmt 2794331766Sken * @brief Generate the indexed end of a section in a management XML document. 2795331766Sken * 2796331766Sken * @par Description 2797331766Sken * This function ends a section. The XML information is appended to 2798331766Sken * the textbuf. 2799331766Sken * 2800331766Sken * @param textbuf Pointer to the driver dump text buffer. 2801331766Sken * @param name Name of the section. 2802331766Sken * @param index Index number of this instance of the section. 2803331766Sken * 2804331766Sken * @return None. 2805331766Sken */ 2806331766Sken 2807331766Skenvoid ocs_mgmt_end_section(ocs_textbuf_t *textbuf, const char *name, int index) 2808331766Sken{ 2809331766Sken 2810331766Sken ocs_textbuf_printf(textbuf, "</%s>\n", name); 2811331766Sken 2812331766Sken} 2813331766Sken 2814331766Sken/** 2815331766Sken * @ingroup mgmt 2816331766Sken * @brief Generate a property, with no value, in a management XML document. 2817331766Sken * 2818331766Sken * @par Description 2819331766Sken * This function generates a property name. The XML information is appended to 2820331766Sken * the textbuf. This form of the function is used by the list functions 2821331766Sken * when the property name only (and not the current value) is given. 2822331766Sken * 2823331766Sken * @param textbuf Pointer to the driver dump text buffer. 2824331766Sken * @param mode Defines whether the property is read(r)/write(w)/executable(x). 2825331766Sken * @param name Name of the property. 2826331766Sken * 2827331766Sken * @return None. 2828331766Sken */ 2829331766Sken 2830331766Skenvoid ocs_mgmt_emit_property_name(ocs_textbuf_t *textbuf, int mode, const char *name) 2831331766Sken{ 2832331766Sken ocs_textbuf_printf(textbuf, "<%s mode=\"%s\"/>\n", name, mode_string(mode)); 2833331766Sken} 2834331766Sken 2835331766Sken/** 2836331766Sken * @ingroup mgmt 2837331766Sken * @brief Generate a property with a string value in a management XML document. 2838331766Sken * 2839331766Sken * @par Description 2840331766Sken * This function generates a property name and a string value. 2841331766Sken * The XML information is appended to the textbuf. 2842331766Sken * 2843331766Sken * @param textbuf Pointer to the driver dump text buffer. 2844331766Sken * @param mode Defines whether the property is read(r)/write(w)/executable(x). 2845331766Sken * @param name Name of the property. 2846331766Sken * @param value Value of the property. 2847331766Sken * 2848331766Sken * @return None. 2849331766Sken */ 2850331766Sken 2851331766Skenvoid ocs_mgmt_emit_string(ocs_textbuf_t *textbuf, int mode, const char *name, const char *value) 2852331766Sken{ 2853331766Sken ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), value, name); 2854331766Sken} 2855331766Sken 2856331766Sken/** 2857331766Sken * @ingroup mgmt 2858331766Sken * @brief Generate a property with an integer value in a management XML document. 2859331766Sken * 2860331766Sken * @par Description 2861331766Sken * This function generates a property name and an integer value. 2862331766Sken * The XML information is appended to the textbuf. 2863331766Sken * 2864331766Sken * @param textbuf Pointer to driver dump text buffer. 2865331766Sken * @param mode Defines whether the property is read(r)/write(w)/executable(x). 2866331766Sken * @param name Name of the property. 2867331766Sken * @param fmt A printf format for formatting the integer value. 2868331766Sken * 2869331766Sken * @return none 2870331766Sken */ 2871331766Sken 2872331766Skenvoid ocs_mgmt_emit_int(ocs_textbuf_t *textbuf, int mode, const char *name, const char *fmt, ...) 2873331766Sken{ 2874331766Sken va_list ap; 2875331766Sken char valuebuf[64]; 2876331766Sken 2877331766Sken va_start(ap, fmt); 2878331766Sken ocs_vsnprintf(valuebuf, sizeof(valuebuf), fmt, ap); 2879331766Sken va_end(ap); 2880331766Sken 2881331766Sken ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), valuebuf, name); 2882331766Sken} 2883331766Sken 2884331766Sken/** 2885331766Sken * @ingroup mgmt 2886331766Sken * @brief Generate a property with a boolean value in a management XML document. 2887331766Sken * 2888331766Sken * @par Description 2889331766Sken * This function generates a property name and a boolean value. 2890331766Sken * The XML information is appended to the textbuf. 2891331766Sken * 2892331766Sken * @param textbuf Pointer to the driver dump text buffer. 2893331766Sken * @param mode Defines whether the property is read(r)/write(w)/executable(x). 2894331766Sken * @param name Name of the property. 2895331766Sken * @param value Boolean value to be added to the textbuf. 2896331766Sken * 2897331766Sken * @return None. 2898331766Sken */ 2899331766Sken 2900331766Skenvoid ocs_mgmt_emit_boolean(ocs_textbuf_t *textbuf, int mode, const char *name, int value) 2901331766Sken{ 2902331766Sken char *valuebuf = value ? "true" : "false"; 2903331766Sken 2904331766Sken ocs_textbuf_printf(textbuf, "<%s mode=\"%s\">%s</%s>\n", name, mode_string(mode), valuebuf, name); 2905331766Sken} 2906331766Sken 2907331766Skenstatic char *mode_string(int mode) 2908331766Sken{ 2909331766Sken static char mode_str[4]; 2910331766Sken 2911331766Sken mode_str[0] = '\0'; 2912331766Sken if (mode & MGMT_MODE_RD) { 2913331766Sken strcat(mode_str, "r"); 2914331766Sken } 2915331766Sken if (mode & MGMT_MODE_WR) { 2916331766Sken strcat(mode_str, "w"); 2917331766Sken } 2918331766Sken if (mode & MGMT_MODE_EX) { 2919331766Sken strcat(mode_str, "x"); 2920331766Sken } 2921331766Sken 2922331766Sken return mode_str; 2923331766Sken 2924331766Sken} 2925