Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_mgmt.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /**
34  * @file
35  * The ocs_mgmt top level functions for Fibre Channel.
36  */
37 
38 /**
39  * @defgroup mgmt Management Functions
40  */
41 
42 #include "ocs.h"
43 #include "ocs_mgmt.h"
44 #include "ocs_vpd.h"
45 #include "ocs_recovery.h"
46 
47 /*
48  * Lancer board temperature command helper structure.
49  */
50 typedef struct ocs_mgmt_lancer_temp_result_s {
51  ocs_t *ocs;
52  ocs_sem_t waitsem;
54  int32_t status;
56 
57 /* Executables*/
58 
59 static int ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
60 #if !defined(OCS_USPACE_SPDK)
61 static int ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
62 #endif
63 static int ocs_mgmt_function_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
64 static int ocs_mgmt_port_migration(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
65 static int ocs_mgmt_read_parity_stats(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
66  void *arg_out, uint32_t arg_out_length);
67 
68 static void ocs_mgmt_fw_write_cb(int32_t status, int32_t ext_status, uint32_t actual_write_length,
69  uint32_t change_status, void *arg);
70 static int ocs_mgmt_force_assert(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void*, uint32_t);
71 
72 #if defined(OCS_INCLUDE_RAMD)
73 static int32_t
74 ocs_mgmt_read_phys(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
75 #endif
76 
77 
78 /* Getters */
79 
80 static void get_nodes_count(ocs_t *, char *, ocs_textbuf_t*);
81 static void get_desc(ocs_t *, char *, ocs_textbuf_t*);
82 static void get_fw_rev(ocs_t *, char *, ocs_textbuf_t*);
83 static void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t*);
84 static void get_ipl(ocs_t *, char *, ocs_textbuf_t*);
85 static void get_wwnn(ocs_t *, char *, ocs_textbuf_t*);
86 static void get_wwpn(ocs_t *, char *, ocs_textbuf_t*);
87 static void get_sn(ocs_t *, char *, ocs_textbuf_t*);
88 static void get_pn(ocs_t *, char *, ocs_textbuf_t*);
89 static void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t*);
90 static void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t*);
91 static void get_asic_id(ocs_t *, char *, ocs_textbuf_t*);
92 static void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t*);
93 static void get_pci_device(ocs_t *, char *, ocs_textbuf_t*);
94 static void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t*);
95 static void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t*);
96 static void get_businfo(ocs_t *, char *, ocs_textbuf_t*);
97 static void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t*);
98 static void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t*);
99 static void get_active_xri_count(ocs_t *, char *, ocs_textbuf_t*);
100 static void get_active_rpi_count(ocs_t *, char *, ocs_textbuf_t*);
101 static void get_lip_count(ocs_t *, char *, ocs_textbuf_t*);
102 static void get_hw_rev1(ocs_t *, char *, ocs_textbuf_t*);
103 static void get_hw_rev2(ocs_t *, char *, ocs_textbuf_t*);
104 static void get_hw_rev3(ocs_t *, char *, ocs_textbuf_t*);
105 static void get_fw_dump_present(ocs_t *, char *, ocs_textbuf_t*);
106 static void get_fw_dump_max_size(ocs_t *, char *, ocs_textbuf_t*);
107 static void get_debug_mq_dump(ocs_t*, char*, ocs_textbuf_t*);
108 static void get_debug_cq_dump(ocs_t*, char*, ocs_textbuf_t*);
109 static void get_debug_wq_dump(ocs_t*, char*, ocs_textbuf_t*);
110 static void get_debug_eq_dump(ocs_t*, char*, ocs_textbuf_t*);
111 static void get_logmask(ocs_t*, char*, ocs_textbuf_t*);
112 static void get_current_speed(ocs_t*, char*, ocs_textbuf_t*);
113 static void get_current_topology(ocs_t*, char*, ocs_textbuf_t*);
114 static void get_current_link_state(ocs_t*, char*, ocs_textbuf_t*);
115 static void get_logical_link_speed(ocs_t *, char *, ocs_textbuf_t *);
116 static void get_logical_link_speed(ocs_t*, char*, ocs_textbuf_t*);
117 static void get_configured_speed(ocs_t*, char*, ocs_textbuf_t*);
118 static void get_configured_topology(ocs_t*, char*, ocs_textbuf_t*);
119 static void get_configured_link_state(ocs_t*, char*, ocs_textbuf_t*);
120 #if defined(ENABLE_FABRIC_EMULATION)
121 static void get_femul_enable(ocs_t*, char*, ocs_textbuf_t*);
122 #endif
123 static void get_linkcfg(ocs_t*, char*, ocs_textbuf_t*);
124 static void get_req_wwnn(ocs_t*, char*, ocs_textbuf_t*);
125 static void get_req_wwpn(ocs_t*, char*, ocs_textbuf_t*);
126 static void get_nodedb_mask(ocs_t*, char*, ocs_textbuf_t*);
127 static void get_profile_list(ocs_t*, char*, ocs_textbuf_t*);
128 static void get_active_profile(ocs_t*, char*, ocs_textbuf_t*);
129 static void get_port_protocol(ocs_t*, char*, ocs_textbuf_t*);
130 static void get_driver_version(ocs_t*, char*, ocs_textbuf_t*);
131 static void get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
132 static void get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
133 static void get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
134 static void get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
135 static void get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
136 static void get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
137 static void get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
138 static void get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
139 static void get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
140 static void get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
141 static void get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
142 static void get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
143 static void get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf);
144 
145 /* Setters */
146 static int set_debug_mq_dump(ocs_t*, char*, char*);
147 static int set_debug_cq_dump(ocs_t*, char*, char*);
148 static int set_debug_wq_dump(ocs_t*, char*, char*);
149 static int set_debug_eq_dump(ocs_t*, char*, char*);
150 static int set_logmask(ocs_t*, char*, char*);
151 static int set_configured_speed(ocs_t*, char*, char*);
152 static int set_configured_topology(ocs_t*, char*, char*);
153 static int set_configured_link_state(ocs_t*, char*, char*);
154 #if defined(ENABLE_FABRIC_EMULATION)
155 static int set_femul_enable(ocs_t*, char*, char*);
156 #endif
157 static int set_linkcfg(ocs_t*, char*, char*);
158 static int set_req_wwnn(ocs_t*, char*, char*);
159 static int set_req_wwpn(ocs_t*, char*, char*);
160 static int set_nodedb_mask(ocs_t*, char*, char*);
161 static int set_port_protocol(ocs_t*, char*, char*);
162 static int set_active_profile(ocs_t*, char*, char*);
163 static int set_tgt_rscn_delay(ocs_t*, char*, char*);
164 static int set_tgt_rscn_period(ocs_t*, char*, char*);
165 static int set_inject_drop_cmd(ocs_t*, char*, char*);
166 static int set_inject_free_drop_cmd(ocs_t*, char*, char*);
167 static int set_inject_drop_data(ocs_t*, char*, char*);
168 static int set_inject_drop_resp(ocs_t*, char*, char*);
169 static int set_cmd_err_inject(ocs_t*, char*, char*);
170 static int set_cmd_delay_value(ocs_t*, char*, char*);
171 static int set_nv_wwn(ocs_t*, char*, char*);
172 static int set_loglevel(ocs_t*, char*, char*);
173 
174 static void ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg);
175 extern int32_t ocs_read_temperature_lancer(ocs_t *ocs, void *buf, uint32_t buf_len);
176 
177 #if defined(OCS_INCLUDE_RAMD)
178 static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr);
179 #endif
180 
182  {"nodes_count", get_nodes_count, NULL, NULL},
183  {"desc", get_desc, NULL, NULL},
184  {"fw_rev", get_fw_rev, NULL, NULL},
185  {"fw_rev2", get_fw_rev2, NULL, NULL},
186  {"ipl", get_ipl, NULL, NULL},
187  {"hw_rev1", get_hw_rev1, NULL, NULL},
188  {"hw_rev2", get_hw_rev2, NULL, NULL},
189  {"hw_rev3", get_hw_rev3, NULL, NULL},
190  {"wwnn", get_wwnn, NULL, NULL},
191  {"wwpn", get_wwpn, NULL, NULL},
192  {"sn", get_sn, NULL, NULL},
193  {"pn", get_pn, NULL, NULL},
194  {"sli4_intf_reg", get_sli4_intf_reg, NULL, NULL},
195  {"phy_port_num", get_phy_port_num, NULL, NULL},
196  {"asic_id_reg", get_asic_id, NULL, NULL},
197  {"pci_vendor", get_pci_vendor, NULL, NULL},
198  {"pci_device", get_pci_device, NULL, NULL},
199  {"pci_subsystem_vendor", get_pci_subsystem_vendor, NULL, NULL},
200  {"pci_subsystem_device", get_pci_subsystem_device, NULL, NULL},
201  {"businfo", get_businfo, NULL, NULL},
202  {"sfp_a0", get_sfp_a0, NULL, NULL},
203  {"sfp_a2", get_sfp_a2, NULL, NULL},
204  {"active_rpi_count", get_active_rpi_count, NULL, NULL},
205  {"active_xri_count", get_active_xri_count, NULL, NULL},
206  {"lip_count", get_lip_count, NULL, NULL},
207  {"profile_list", get_profile_list, NULL, NULL},
208  {"driver_version", get_driver_version, NULL, NULL},
209  {"current_speed", get_current_speed, NULL, NULL},
210  {"current_topology", get_current_topology, NULL, NULL},
211  {"current_link_state", get_current_link_state, NULL, NULL},
212  {"logical_link_speed", get_logical_link_speed, NULL, NULL},
213  {"chip_type", get_chip_type, NULL, NULL},
214  {"configured_speed", get_configured_speed, set_configured_speed, NULL},
215  {"configured_topology", get_configured_topology, set_configured_topology, NULL},
216  {"configured_link_state", get_configured_link_state, set_configured_link_state, NULL},
217 #if defined(ENABLE_FABRIC_EMULATION)
218  {"femul_enable", get_femul_enable, set_femul_enable, NULL},
219 #endif
220  {"debug_mq_dump", get_debug_mq_dump, set_debug_mq_dump, NULL},
221  {"debug_cq_dump", get_debug_cq_dump, set_debug_cq_dump, NULL},
222  {"debug_wq_dump", get_debug_wq_dump, set_debug_wq_dump, NULL},
223  {"debug_eq_dump", get_debug_eq_dump, set_debug_eq_dump, NULL},
224  {"logmask", get_logmask, set_logmask, NULL},
225  {"loglevel", get_loglevel, set_loglevel, NULL},
226  {"linkcfg", get_linkcfg, set_linkcfg, NULL},
227  {"requested_wwnn", get_req_wwnn, set_req_wwnn, NULL},
228  {"requested_wwpn", get_req_wwpn, set_req_wwpn, NULL},
229  {"nodedb_mask", get_nodedb_mask, set_nodedb_mask, NULL},
230  {"port_protocol", get_port_protocol, set_port_protocol, NULL},
231  {"active_profile", get_active_profile, set_active_profile, NULL},
232  {"fw_dump_present", get_fw_dump_present, NULL, NULL},
233  {"fw_dump_max_size", get_fw_dump_max_size, NULL, NULL},
234  {"firmware_write", NULL, NULL, ocs_mgmt_firmware_write},
235 #if !defined(OCS_USPACE_SPDK)
236  {"firmware_reset", NULL, NULL, ocs_mgmt_firmware_reset},
237 #endif
238  {"function_reset", NULL, NULL, ocs_mgmt_function_reset},
239  {"port_migration", NULL, NULL, ocs_mgmt_port_migration},
240 #if defined(OCS_INCLUDE_RAMD)
241  {"read_phys", NULL, NULL, ocs_mgmt_read_phys},
242 #endif
243  {"force_assert", NULL, NULL, ocs_mgmt_force_assert},
244  {"get_parity_stats", NULL, NULL, ocs_mgmt_read_parity_stats},
245  {"tgt_rscn_delay", get_tgt_rscn_delay, set_tgt_rscn_delay, NULL},
246  {"tgt_rscn_period", get_tgt_rscn_period, set_tgt_rscn_period, NULL},
247  {"inject_drop_cmd", get_inject_drop_cmd, set_inject_drop_cmd, NULL},
248  {"inject_free_drop_cmd", get_inject_free_drop_cmd, set_inject_free_drop_cmd, NULL},
249  {"inject_drop_data", get_inject_drop_data, set_inject_drop_data, NULL},
250  {"inject_drop_resp", get_inject_drop_resp, set_inject_drop_resp, NULL},
251  {"cmd_err_inject", get_cmd_err_inject, set_cmd_err_inject, NULL},
252  {"cmd_delay_value", get_cmd_delay_value, set_cmd_delay_value, NULL},
253  {"nv_wwpn", get_nv_wwpn, NULL, NULL},
254  {"nv_wwnn", get_nv_wwnn, NULL, NULL},
255  {"nv_wwn", NULL, set_nv_wwn, NULL},
256  {"node_abort_cnt", get_node_abort_cnt, NULL, NULL},
257 };
258 
259 /**
260  * @ingroup mgmt
261  * @brief Get a list of options supported by the driver.
262  *
263  * @par Description
264  * This is the top level "get list" handler for the driver. It
265  * performs the following:
266  * - Adds entries to the textbuf for any actions supported by this level in the driver.
267  * - Calls a back-end function to add any actions supported by the back-end.
268  * - Calls a function on each child (domain) to recursively add supported actions.
269  *
270  * @param ocs Pointer to the ocs structure.
271  * @param textbuf Pointer to an ocs_textbuf, which is used to accumulate the results.
272  *
273  * @return Returns 0 on success, or a negative value on failure.
274  */
275 
276 void
277 ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
278 {
279  ocs_domain_t *domain;
280  uint32_t i;
281  int access;
282 
283  ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
284 
285  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
286  access = 0;
287  if (mgmt_table[i].get_handler) {
288  access |= MGMT_MODE_RD;
289  }
290  if (mgmt_table[i].set_handler) {
291  access |= MGMT_MODE_WR;
292  }
293  if (mgmt_table[i].action_handler) {
294  access |= MGMT_MODE_EX;
295  }
296  ocs_mgmt_emit_property_name(textbuf, access, mgmt_table[i].name);
297  }
298 
299  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_list_handler)) {
300  ocs->mgmt_functions->get_list_handler(textbuf, ocs);
301  }
302 
303  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_list_handler)) {
304  ocs->tgt_mgmt_functions->get_list_handler(textbuf, &(ocs->tgt_ocs));
305  }
306 
307  /* Have each of my children add their actions */
308  if (ocs_device_lock_try(ocs) == TRUE) {
309 
310  /* If we get here then we are holding the device lock */
311  ocs_list_foreach(&ocs->domain_list, domain) {
312  if ((domain->mgmt_functions) && (domain->mgmt_functions->get_list_handler)) {
313  domain->mgmt_functions->get_list_handler(textbuf, domain);
314  }
315  }
316  ocs_device_unlock(ocs);
317  }
318 
319  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
320 
321 }
322 
323 /**
324  * @ingroup mgmt
325  * @brief Return the value of a management item.
326  *
327  * @par Description
328  * This is the top level "get" handler for the driver. It
329  * performs the following:
330  * - Checks that the qualifier portion of the name begins with my qualifier (ocs).
331  * - If the remaining part of the name matches a parameter that is known at this level,
332  * writes the value into textbuf.
333  * - If the name is not known, sends the request to the back-ends to fulfill (if possible).
334  * - If the request has not been fulfilled by the back-end,
335  * passes the request to each of the children (domains) to
336  * have them (recursively) try to respond.
337  *
338  * In passing the request to other entities, the request is considered to be answered
339  * when a response has been written into textbuf, indicated by textbuf->buffer_written
340  * being non-zero.
341  *
342  * @param ocs Pointer to the ocs structure.
343  * @param name Name of the status item to be retrieved.
344  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
345  *
346  * @return Returns 0 if the value was found and returned, or -1 if an error occurred.
347  */
348 
349 
350 int
351 ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
352 {
353  ocs_domain_t *domain;
354  char qualifier[6];
355  int retval = -1;
356  uint32_t i;
357 
358  ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
359 
360 
361  snprintf(qualifier, sizeof(qualifier), "/ocs");
362 
363  /* See if the name starts with my qualifier. If not then this request isn't for me */
364  if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
365  char *unqualified_name = name + strlen(qualifier) + 1;
366 
367  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
368  if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
369  if (mgmt_table[i].get_handler) {
370  mgmt_table[i].get_handler(ocs, name, textbuf);
371  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
372  return 0;
373  }
374  }
375  }
376 
377  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_handler)) {
378  retval = ocs->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, ocs);
379  }
380 
381  if (retval != 0) {
382  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_handler)) {
383  retval = ocs->tgt_mgmt_functions->get_handler(textbuf, qualifier,
384  (char*)name, &(ocs->tgt_ocs));
385  }
386  }
387 
388  if (retval != 0) {
389  if (!ocs_device_lock_try_timeout(ocs, 1000, 3)) {
390  ocs_log_err(ocs, " Failed to acquire device lock\n");
391  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
392  return -EBUSY;
393  }
394 
395  /* Return success if domain list is empty */
396  if (ocs_list_empty(&ocs->domain_list)) {
397  ocs_device_unlock(ocs);
398  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
399  retval = 0;
400  return retval;
401  }
402 
403  /* The driver didn't handle it, pass it to each domain */
404  ocs_list_foreach(&ocs->domain_list, domain) {
405  if ((domain->mgmt_functions) && (domain->mgmt_functions->get_handler)) {
406  retval = domain->mgmt_functions->get_handler(textbuf, qualifier, (char*)name, domain);
407  }
408 
409  if (retval == 0) {
410  break;
411  }
412 
413 
414  }
415 
416  ocs_device_unlock(ocs);
417  }
418 
419  }
420 
421  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
422 
423  return retval;
424 }
425 
426 
427 /**
428  * @ingroup mgmt
429  * @brief Set the value of a mgmt item.
430  *
431  * @par Description
432  * This is the top level "set" handler for the driver. It
433  * performs the following:
434  * - Checks that the qualifier portion of the name begins with my qualifier (ocs).
435  * - If the remaining part of the name matches a parameter that is known at this level,
436  * calls the correct function to change the configuration.
437  * - If the name is not known, sends the request to the back-ends to fulfill (if possible).
438  * - If the request has not been fulfilled by the back-end, passes the request to each of the
439  * children (domains) to have them (recursively) try to respond.
440  *
441  * In passing the request to other entities, the request is considered to be handled
442  * if the function returns 0.
443  *
444  * @param ocs Pointer to the ocs structure.
445  * @param name Name of the property to be changed.
446  * @param value Requested new value of the property.
447  *
448  * @return Returns 0 if the configuration value was updated, or -1 otherwise.
449  */
450 
451 int
452 ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
453 {
454  ocs_domain_t *domain;
455  int result = -1;
456  char qualifier[80];
457  uint32_t i;
458 
459  snprintf(qualifier, sizeof(qualifier), "/ocs");
460 
461  /* If it doesn't start with my qualifier I don't know what to do with it */
462  if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
463  char *unqualified_name = name + strlen(qualifier) +1;
464 
465  /* See if it's a value I can set */
466  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
467  if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
468  if (mgmt_table[i].set_handler) {
469  return mgmt_table[i].set_handler(ocs, name, value);
470  }
471  }
472  }
473 
474  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->set_handler)) {
475  result = ocs->mgmt_functions->set_handler(qualifier, name, (char *)value, ocs);
476  }
477 
478  if (result != 0) {
479  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->set_handler)) {
480  result = ocs->tgt_mgmt_functions->set_handler(qualifier, name,
481  (char *)value, &(ocs->tgt_ocs));
482  }
483  }
484 
485  /* If I didn't know how to set this config value pass the request to each of my children */
486  if (result != 0) {
487  if (!ocs_device_lock_try_timeout(ocs, 1000, 3)) {
488  ocs_log_err(ocs, " Failed to acquire device lock\n");
489  return -EBUSY;
490  }
491  ocs_list_foreach(&ocs->domain_list, domain) {
492  if ((domain->mgmt_functions) && (domain->mgmt_functions->set_handler)) {
493  result = domain->mgmt_functions->set_handler(qualifier, name, (char*)value, domain);
494  }
495  if (result == 0) {
496  break;
497  }
498  }
499  ocs_device_unlock(ocs);
500  }
501 
502 
503  }
504 
505  return result;
506 }
507 
508 /**
509  * @ingroup mgmt
510  * @brief Perform a management action.
511  *
512  * @par Description
513  * This is the top level "exec" handler for the driver. It
514  * performs the following:
515  * - Checks that the qualifier portion of the name begins with my qualifier (ocs).
516  * - If the remaining part of the name matches an action that is known at this level,
517  * calls the correct function to perform the action.
518  * - If the name is not known, sends the request to the back-ends to fulfill (if possible).
519  * - If the request has not been fulfilled by the back-end, passes the request to each of the
520  * children (domains) to have them (recursively) try to respond.
521  *
522  * In passing the request to other entities, the request is considered to be handled
523  * if the function returns 0.
524  *
525  * @param ocs Pointer to the ocs structure.
526  * @param action Name of the action to be performed.
527  * @param arg_in Pointer to an argument being passed to the action.
528  * @param arg_in_length Length of the argument pointed to by @c arg_in.
529  * @param arg_out Pointer to an argument being passed to the action.
530  * @param arg_out_length Length of the argument pointed to by @c arg_out.
531  *
532  * @return Returns 0 if the action was completed, or -1 otherwise.
533  *
534  *
535  */
536 
537 int
538 ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in,
539  uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
540 {
541  ocs_domain_t *domain;
542  int result = -1;
543  char qualifier[80];
544  uint32_t i;
545 
546  snprintf(qualifier, sizeof(qualifier), "/ocs");
547 
548  /* If it doesn't start with my qualifier I don't know what to do with it */
549  if (ocs_strncmp(action, qualifier, strlen(qualifier)) == 0) {
550  char *unqualified_name = action + strlen(qualifier) +1;
551 
552  /* See if it's an action I can perform */
553  for (i=0;i<ARRAY_SIZE(mgmt_table); i++) {
554  if (ocs_strcmp(unqualified_name, mgmt_table[i].name) == 0) {
555  if (mgmt_table[i].action_handler) {
556  return mgmt_table[i].action_handler(ocs, action, arg_in, arg_in_length,
557  arg_out, arg_out_length);
558  }
559 
560  }
561  }
562 
563  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->exec_handler)) {
564  result = ocs->mgmt_functions->exec_handler(qualifier, action, arg_in, arg_in_length,
565  arg_out, arg_out_length, ocs);
566  }
567 
568  if (result != 0) {
569  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->exec_handler)) {
570  result = ocs->tgt_mgmt_functions->exec_handler(qualifier, action,
571  arg_in, arg_in_length, arg_out, arg_out_length,
572  &(ocs->tgt_ocs));
573  }
574  }
575 
576  /* If I didn't know how to do this action pass the request to each of my children */
577  if (result != 0) {
578  ocs_domain_exec_arg_t *domain_exec_args;
579 
580  if (ocs_list_empty(&ocs->domain_list)) {
581  ocs_log_err(ocs, "Error: domain is empty\n");
582  return -ENODEV;
583  }
584  domain_exec_args = ocs_malloc(ocs, sizeof(ocs_domain_exec_arg_t),
585  OCS_M_NOWAIT | OCS_M_ZERO);
586  if (domain_exec_args == NULL) {
587  ocs_log_err(ocs, "Failed to allocate memory\n");
588  return -ENOMEM;
589  }
590  domain_exec_args->arg_out = ocs_malloc(ocs, arg_out_length, OCS_M_NOWAIT | OCS_M_ZERO);
591  if (domain_exec_args->arg_out == NULL) {
592  ocs_free(ocs, domain_exec_args, sizeof(ocs_domain_exec_arg_t));
593  ocs_log_err(ocs, "Failed to allocate memory\n");
594  return -ENOMEM;
595  }
596  domain_exec_args->arg_out_length = arg_out_length;
597  domain_exec_args->arg_in_length = arg_in_length;
598  domain_exec_args->arg_in = arg_in;
599  domain_exec_args->exec_cb = ocs_mgmt_domain_exec_cb;
600  ocs_sem_init(&domain_exec_args->sem, 0, "domain_exec_sem");
601  ocs_atomic_init(&domain_exec_args->ref_cnt, 2);
602 
603  ocs_device_lock(ocs);
604  ocs_list_foreach(&ocs->domain_list, domain) {
605  if ((domain->mgmt_functions) && (domain->mgmt_functions->exec_handler)) {
606  result = domain->mgmt_functions->exec_handler(qualifier, action,
607  domain_exec_args, sizeof(ocs_domain_exec_arg_t),
608  NULL, 0, domain);
609  }
610  if (result == 0) {
611  break;
612  }
613  }
614  ocs_device_unlock(ocs);
615  if (ocs_sem_p(&domain_exec_args->sem, OCS_SEM_FOREVER)) {
616  ocs_log_err(ocs, "ocs_sem_p failed\n");
617  result = -ENXIO;
618  }
619  if (ocs_atomic_sub_and_test(&domain_exec_args->ref_cnt, 1)) {
620  if (ocs_copy_to_user(arg_out, domain_exec_args->arg_out, arg_out_length))
621  ocs_log_err(ocs, "Error: copy to user buffer is failed\n");
622  ocs_free(ocs, domain_exec_args->arg_out, arg_out_length);
623  ocs_free(ocs, domain_exec_args, sizeof(*domain_exec_args));
624  }
625  }
626  }
627 
628  return result;
629 }
630 
631 void
632 ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
633 {
634  ocs_domain_t *domain;
635  uint32_t i;
636 
637  ocs_mgmt_start_unnumbered_section(textbuf, "ocs");
638 
639  for (i=0;i<ARRAY_SIZE(mgmt_table);i++) {
640  if (mgmt_table[i].get_handler) {
641  mgmt_table[i].get_handler(ocs, mgmt_table[i].name, textbuf);
642  } else if (mgmt_table[i].action_handler) {
643  /* No get_handler, but there's an action_handler. Just report
644  the name */
645  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, mgmt_table[i].name);
646  }
647  }
648 
649  if ((ocs->mgmt_functions) && (ocs->mgmt_functions->get_all_handler)) {
650  ocs->mgmt_functions->get_all_handler(textbuf, ocs);
651  }
652 
653  if ((ocs->tgt_mgmt_functions) && (ocs->tgt_mgmt_functions->get_all_handler)) {
654  ocs->tgt_mgmt_functions->get_all_handler(textbuf, &(ocs->tgt_ocs));
655  }
656 
657  if (!ocs_device_lock_try_timeout(ocs, 1000, 3)) {
658  ocs_log_err(ocs, " Failed to acquire device lock\n");
659  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
660  return;
661  }
662  ocs_list_foreach(&ocs->domain_list, domain) {
663  if ((domain->mgmt_functions) && (domain->mgmt_functions->get_all_handler)) {
664  domain->mgmt_functions->get_all_handler(textbuf, domain);
665  }
666  }
667  ocs_device_unlock(ocs);
668 
669  ocs_mgmt_end_unnumbered_section(textbuf, "ocs");
670 }
671 
672 #if defined(OCS_INCLUDE_RAMD)
673 static int32_t
674 ocs_mgmt_read_phys(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
675 {
676  uint32_t length;
677  char addr_str[80];
678  uintptr_t target_addr;
679  void* vaddr = NULL;
680  ocs_ramdisc_t **ramdisc_array;
681  uint32_t ramdisc_count;
682 
683 
684  if ((arg_in == NULL) ||
685  (arg_in_length == 0) ||
686  (arg_out == NULL) ||
687  (arg_out_length == 0)) {
688  return -1;
689  }
690 
691  if (arg_in_length > 80) {
692  arg_in_length = 80;
693  }
694 
695  if (ocs_copy_from_user(addr_str, arg_in, arg_in_length)) {
696  ocs_log_test(ocs, "Failed to copy addr from user\n");
697  return -EFAULT;
698  }
699 
700  target_addr = (uintptr_t)ocs_strtoul(addr_str, NULL, 0);
701  /* addr_str must be the physical address of a buffer that was reported
702  * in an SGL. Search ramdiscs looking for a segment that contains that
703  * physical address
704  */
705 
706  if (ocs->tgt_ocs.use_global_ramd) {
707  /* Only one target */
708  ramdisc_count = ocs->tgt_ocs.rdisc_count;
709  ramdisc_array = ocs->tgt_ocs.rdisc;
710  vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
711  } else {
712  /* Multiple targets. Each target is on a sport */
713  uint32_t domain_idx;
714 
715  for (domain_idx=0; domain_idx<ocs->domain_instance_count; domain_idx++) {
716  ocs_domain_t *domain;
717  uint32_t sport_idx;
718 
719  domain = ocs_domain_get_instance(ocs, domain_idx);
720  for (sport_idx=0; sport_idx < domain->sport_instance_count; sport_idx++) {
721  ocs_sport_t *sport;
722 
723  sport = ocs_sport_get_instance(domain, sport_idx);
724  ramdisc_count = sport->tgt_sport.rdisc_count;
725  ramdisc_array = sport->tgt_sport.rdisc;
726  vaddr = find_address_in_target(ramdisc_array, ramdisc_count, target_addr);
727 
728  if (vaddr != NULL) {
729  break;
730  }
731  }
732  }
733  }
734 
735 
736 
737 
738  length = arg_out_length;
739 
740  if (vaddr != NULL) {
741 
742  if (ocs_copy_to_user(arg_out, vaddr, length)) {
743  ocs_log_test(ocs, "Failed to copy buffer to user\n");
744  return -EFAULT;
745  }
746 
747  return 0;
748  } else {
749 
750  return -EFAULT;
751  }
752 
753 }
754 
755 /*
756  * This function searches a target for a given physical address.
757  * The target is made up of a number of LUNs, each represented by
758  * a ocs_ramdisc_t.
759  */
760 static void* find_address_in_target(ocs_ramdisc_t **ramdisc_array, uint32_t ramdisc_count, uintptr_t target_addr)
761 {
762  void *vaddr = NULL;
763  uint32_t ramdisc_idx;
764 
765  /* Check each ramdisc */
766  for (ramdisc_idx=0; ramdisc_idx<ramdisc_count; ramdisc_idx++) {
767  uint32_t segment_idx;
768  ocs_ramdisc_t *rdisc;
769  rdisc = ramdisc_array[ramdisc_idx];
770  /* Check each segment in the ramdisc */
771  for (segment_idx=0; segment_idx<rdisc->segment_count; segment_idx++) {
772  ramdisc_segment_t *segment = rdisc->segments[segment_idx];
773  uintptr_t segment_start;
774  uintptr_t segment_end;
775  uint32_t offset;
776 
777  segment_start = segment->data_segment.phys;
778  segment_end = segment->data_segment.phys + segment->data_segment.size - 1;
779  if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
780  /* Found the target address */
781  offset = target_addr - segment_start;
782  vaddr = (uint32_t*)segment->data_segment.virt + offset;
783  }
784 
785  if (rdisc->dif_separate) {
786  segment_start = segment->dif_segment.phys;
787  segment_end = segment->data_segment.phys + segment->dif_segment.size - 1;
788  if ((target_addr >= segment_start) && (target_addr <= segment_end)) {
789  /* Found the target address */
790  offset = target_addr - segment_start;
791  vaddr = (uint32_t*)segment->dif_segment.virt + offset;
792  }
793  }
794 
795  if (vaddr != NULL) {
796  break;
797  }
798 
799  }
800 
801  if (vaddr != NULL) {
802  break;
803  }
804 
805 
806  }
807 
808  return vaddr;
809 }
810 #endif
811 
812 
813 #if !defined(OCS_USPACE_SPDK)
814 static int32_t
815 ocs_mgmt_firmware_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
816 {
817  return ocs_fw_reset(ocs);
818 }
819 #endif
820 
821 static int32_t
822 ocs_mgmt_function_reset(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
823 {
824  int32_t rc;
825  ocs_xport_stats_t prev_state;
826 
827  /* Save the previous link state */
828  prev_state.value = 0;
829  ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &prev_state);
830 
831  ocs_device_detach(ocs);
832  rc = ocs_device_attach(ocs);
833  if (!rc && (prev_state.value == OCS_XPORT_PORT_ONLINE)) {
834  /* Bring back the link to old up state. */
836  }
837 
838  return rc;
839 }
840 
841 static int32_t
842 ocs_mgmt_port_migration(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
843 {
844 #if !defined(OCS_USPACE_SPDK)
846 #else
847  return -1;
848 #endif
849 }
850 
851 #define FW_WRITE_BUFSIZE 64*1024
852 
853 typedef struct ocs_mgmt_fw_write_result {
854  ocs_sem_t semaphore;
855  int32_t status;
856  uint32_t actual_xfer;
857  uint32_t change_status;
858  uint32_t ext_status;
860 
861 
862 static int32_t
863 ocs_mgmt_firmware_write(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
864 {
865  int rc = 0;
866  uint32_t bytes_left;
867  uint32_t xfer_size;
868  uint32_t offset;
869  uint8_t *userp;
870  ocs_dma_t dma;
871  int last = 0;
873  uint32_t change_status = 0;
874  char status_str[80];
875 
876  ocs_sem_init(&(result.semaphore), 0, "fw_write");
877 
878  bytes_left = buf_len;
879  offset = 0;
880  userp = (uint8_t *)buf;
881 
882  if (ocs_dma_alloc(ocs, &dma, FW_WRITE_BUFSIZE, 4096)) {
883  ocs_log_err(ocs, "ocs_mgmt_firmware_write: malloc failed");
884  return -ENOMEM;
885  }
886 
887  while (bytes_left > 0) {
888 
889 
890  if (bytes_left > FW_WRITE_BUFSIZE) {
891  xfer_size = FW_WRITE_BUFSIZE;
892  } else {
893  xfer_size = bytes_left;
894  }
895 
896  // Copy xfer_size bytes from user space to kernel buffer
897  if (ocs_copy_from_user(dma.virt, userp, xfer_size)) {
898  rc = -EFAULT;
899  break;
900  }
901 
902  // See if this is the last block
903  if (bytes_left == xfer_size) {
904  last = 1;
905  }
906 
907  // Send the HAL command
908  ocs_hal_firmware_write(&ocs->hal, &dma, xfer_size, offset, last, ocs_mgmt_fw_write_cb, &result);
909 
910  // Wait for semaphore to be signaled when the command completes
911  // TODO: Should there be a timeout on this? If so, how long?
912  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
913  // Undefined failure
914  ocs_log_err(ocs, "ocs_sem_p failed\n");
915  rc = -ENXIO;
916  break;
917  }
918 
919  if (result.actual_xfer == 0) {
920  ocs_log_test(ocs, "actual_write_length is %d\n", result.actual_xfer);
921  rc = -EFAULT;
922  break;
923  }
924 
925  // Check status
926  if (result.status != 0) {
927  ocs_log_err(ocs, "write returned status %d, additional status %d\n",
928  result.status, result.ext_status);
930  ocs_log_err(ocs, "Firmware does not meet minimum version requirement for this IPL\n");
931  rc = -EACCES;
932  } else {
933  rc = -EFAULT;
934  }
935  break;
936  }
937 
938  if (last) {
939  change_status = result.change_status;
940  }
941 
942  bytes_left -= result.actual_xfer;
943  offset += result.actual_xfer;
944  userp += result.actual_xfer;
945 
946  }
947 
948  /* Create string with status and copy to userland */
949  if ((arg_out_length > 0) && (arg_out != NULL)) {
950  if (arg_out_length > sizeof(status_str)) {
951  arg_out_length = sizeof(status_str);
952  }
953  ocs_snprintf(status_str, arg_out_length, "%d", change_status);
954  if (ocs_copy_to_user(arg_out, status_str, arg_out_length)) {
955  ocs_log_test(ocs, "copy to user failed for change_status\n");
956  }
957  }
958 
959 
960  ocs_dma_free(ocs, &dma);
961 
962  return rc;
963 }
964 
965 static void
966 ocs_mgmt_fw_write_cb(int32_t status, int32_t ext_status, uint32_t actual_write_length,
967  uint32_t change_status, void *arg)
968 {
969  ocs_mgmt_fw_write_result_t *result = arg;
970 
971  result->status = status;
972  result->actual_xfer = actual_write_length;
973  result->change_status = change_status;
974  result->ext_status = ext_status;
975 
976  ocs_sem_v(&(result->semaphore));
977 }
978 
979 typedef struct ocs_mgmt_parity_stats_result_s {
980  ocs_sem_t semaphore;
981  int32_t status;
984 
985 static void
986 ocs_mgmt_read_parity_stats_cb(int32_t status, uint8_t num_ulp,
987  ocs_parity_err_count_t *counter, void *arg)
988 {
989  uint8_t i;
991 
992  result->status = status;
993  if (0 == status) {
994  for (i = 0; i < num_ulp; i++) {
995  result->counter[i].pbec = counter[i].pbec;
996  result->counter[i].tpec = counter[i].tpec;
997  }
998  }
999 
1000  ocs_sem_v(&result->semaphore);
1001 }
1002 
1003 static int32_t
1004 ocs_mgmt_read_parity_stats(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length,
1005  void *arg_out, uint32_t arg_out_length)
1006 {
1007  int32_t rc = -1;
1008  bool clear_stats = FALSE;
1009  char arg_str[8] = { '\0' };
1010  uint32_t stats_counter_size = (OCS_MAX_SLI4_ULP * sizeof(ocs_parity_err_count_t));
1012 
1013  if (!arg_out_length || !arg_out)
1014  return rc;
1015 
1016  if (arg_in_length && arg_in) {
1017  if (arg_in_length > 8)
1018  arg_in_length = 8;
1019 
1020  if (ocs_copy_from_user(arg_str, arg_in, arg_in_length)) {
1021  ocs_log_err(ocs, "Failed to copy arg from user\n");
1022  return -EFAULT;
1023  }
1024 
1025  /* Check if we have to clear the ITCM parity stats */
1026  if (0 == ocs_strncmp(arg_str, "clear", ocs_strlen("clear")))
1027  clear_stats = TRUE;
1028  }
1029 
1030  ocs_memset(&result, 0, sizeof(result));
1031  ocs_sem_init(&result.semaphore, 0, "get_parity_stats");
1032  rc = ocs_hal_get_itcm_parity_stats(&ocs->hal, clear_stats, ocs_mgmt_read_parity_stats_cb, &result);
1033  if (rc)
1034  return rc;
1035 
1036  if (ocs_sem_p(&result.semaphore, OCS_SEM_FOREVER)) {
1037  /* Undefined failure */
1038  ocs_log_err(ocs, "ocs_sem_p failed\n");
1039  return -ENXIO;
1040  }
1041 
1042  if (result.status) {
1043  ocs_log_err(ocs, "Read parity stats failed; status: %d\n", result.status);
1044  return -EFAULT;
1045  }
1046 
1047  /* Success; copy the parity stats from result struct to arg_out */
1048  if (arg_out_length > stats_counter_size)
1049  arg_out_length = stats_counter_size;
1050 
1051  if (ocs_copy_to_user(arg_out, result.counter, arg_out_length)) {
1052  ocs_log_err(ocs, "Failed to copy buffer to user\n");
1053  return -EFAULT;
1054  }
1055 
1056  return rc;
1057 }
1058 
1059 void ocs_read_temperature_lancer_cb(int32_t status, uint32_t curr_temp,
1060  uint32_t crit_temp_thr, uint32_t warn_temp_thr,
1061  uint32_t norm_temp_thr, uint32_t fan_off_thr,
1062  uint32_t fan_on_thr, void *arg)
1063 {
1065  ocs_t *ocs = result->ocs;
1066 
1067  ocs_log_debug(ocs, "CB status %08x, curr_temp=%d crit_temp_thr=%d "
1068  "warn_temp_thr %d norm_temp_thr %d foff_thr %d fon_thr %d\n",
1069  status, curr_temp, crit_temp_thr, warn_temp_thr,
1070  norm_temp_thr, fan_off_thr, fan_on_thr);
1071 
1072  result->status = status;
1073  result->resp[0] = curr_temp;
1074  result->resp[1] = crit_temp_thr;
1075  result->resp[2] = warn_temp_thr;
1076  result->resp[3] = norm_temp_thr;
1077  result->resp[4] = fan_off_thr;
1078  result->resp[5] = fan_on_thr;
1079 
1080  ocs_sem_v(&result->waitsem);
1081 }
1082 
1083 int32_t ocs_read_temperature_lancer(ocs_t *ocs, void *buf, uint32_t buf_len)
1084 {
1085  int32_t rc = -1;
1087 
1089  ocs_log_err(ocs, "Insufficient output buffer\n");
1090  return rc;
1091  }
1092 
1093  result = ocs_malloc(ocs, sizeof(ocs_mgmt_lancer_temp_result_t),
1094  OCS_M_ZERO | OCS_M_NOWAIT);
1095  if (result == NULL) {
1096  ocs_log_err(ocs, "Failed to allcoate memory\n");
1097  return rc;
1098  }
1099 
1100  ocs_sem_init(&result->waitsem, 0, "dump_type4_mbox");
1102  result);
1103  if (rc) {
1104  ocs_log_err(ocs, "HAL get temperature failed\n");
1105  goto exit_err;
1106  }
1107 
1108  if (ocs_sem_p(&result->waitsem, OCS_SEM_FOREVER)) {
1109  ocs_log_err(ocs, "ocs_sem_p failed\n");
1110  goto exit_err;
1111  }
1112 
1113  if (result->status != 0) {
1114  ocs_log_err(ocs, "Read temperature command failed status %04x\n",
1115  result->status);
1116  rc = -EFAULT;
1117  goto exit_err;
1118  }
1119 
1120  /* Copy resp to user buffer */
1121  if (ocs_copy_to_user(buf, (uint8_t *)result->resp, sizeof(result->resp))) {
1122  ocs_log_err(ocs, "Failed to copy resp to user buffer\n");
1123  rc = -EFAULT;
1124  }
1125 
1126 exit_err:
1127  if (result)
1128  ocs_free(ocs, result, sizeof(ocs_mgmt_lancer_temp_result_t));
1129 
1130  return rc;
1131 }
1132 
1133 typedef struct ocs_mgmt_sfp_result {
1134  ocs_sem_t semaphore;
1135  ocs_lock_t cb_lock;
1136  int32_t running;
1137  int32_t status;
1138  uint32_t bytes_read;
1139  uint32_t page_data[32];
1141 
1142 static void
1143 ocs_mgmt_sfp_cb(void *os, int32_t status, uint32_t bytes_read, uint32_t *data, void *arg)
1144 {
1145  ocs_mgmt_sfp_result_t *result = arg;
1146  ocs_t *ocs = os;
1147 
1148  ocs_lock(&(result->cb_lock));
1149  result->running++;
1150  if(result->running == 2) {
1151  /* get_sfp() has timed out */
1152  ocs_unlock(&(result->cb_lock));
1153  ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t));
1154  return;
1155  }
1156 
1157  result->status = status;
1158  result->bytes_read = bytes_read;
1159  ocs_memcpy(&result->page_data, data, SFP_PAGE_SIZE);
1160 
1161  ocs_sem_v(&(result->semaphore));
1162  ocs_unlock(&(result->cb_lock));
1163 }
1164 
1165 int32_t ocs_mgmt_get_sfp(ocs_t *ocs, uint16_t page,
1166  void *buf, uint32_t buf_len)
1167 {
1168  int rc = 0;
1169  ocs_mgmt_sfp_result_t *result = ocs_malloc(ocs, sizeof(ocs_mgmt_sfp_result_t), OCS_M_ZERO | OCS_M_NOWAIT);;
1170  if (result == NULL) {
1171  ocs_log_err(ocs, "failed to allocate memory for sfp results\n");
1172  return -1;
1173  }
1174 
1175  ocs_sem_init(&(result->semaphore), 0, "get_sfp");
1176  ocs_lock_init(ocs, &(result->cb_lock), "get_sfp");
1177 
1178  /* Send the HAL command */
1179  rc = ocs_hal_get_sfp(&ocs->hal, page, ocs_mgmt_sfp_cb, result);
1180 
1181  if (rc == OCS_HAL_RTN_SUCCESS) {
1182  /* Wait for semaphore to be signaled when the command completes */
1183  if (ocs_sem_p(&(result->semaphore), 5 * 1000 * 1000) != 0) {
1184  /* Timed out, callback will free memory */
1185  ocs_lock(&(result->cb_lock));
1186  result->running++;
1187  if(result->running == 1) {
1188  ocs_log_err(ocs, "ocs_sem_p failed\n");
1189  ocs_unlock(&(result->cb_lock));
1190  return (-ENXIO);
1191  }
1192  /* sfp_cb() has already executed, proceed as normal */
1193  ocs_unlock(&(result->cb_lock));
1194  }
1195 
1196  /* Check status */
1197  if (result->status != 0) {
1198  ocs_log_test(ocs, "read_transceiver_data returned status %d\n",
1199  result->status);
1200 #define UNSUPPORTED_SFP_ERR_STATUS 0x42
1201  if (result->status == UNSUPPORTED_SFP_ERR_STATUS)
1202  rc = -ENODEV;
1203  else
1204  rc = -EFAULT;
1205  }
1206  } else {
1207  ocs_log_err(ocs, "failed to submit HAL command to get SFP transaciver data\n");
1208  rc = -1;
1209  }
1210 
1211  if (rc == 0) {
1212  rc = (result->bytes_read > buf_len ? buf_len : result->bytes_read);
1213  /* Copy the results back to the supplied buffer */
1214  ocs_memcpy(buf, result->page_data, rc);
1215  }
1216 
1217  if (result)
1218  ocs_free(ocs, result, sizeof(ocs_mgmt_sfp_result_t));
1219  return rc;
1220 }
1221 
1222 static int32_t
1223 ocs_mgmt_force_assert(ocs_t *ocs, char *name, void *buf, uint32_t buf_len, void *arg_out, uint32_t arg_out_length)
1224 {
1225  ocs_assert(FALSE, 0);
1226 }
1227 
1228 static void
1229 get_nodes_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1230 {
1231  ocs_xport_t *xport = ocs->xport;
1232 
1233  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "nodes_count", "%d", xport->nodes_count);
1234 }
1235 
1236 static void
1237 get_driver_version(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1238 {
1239  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "driver_version", ocs->driver_version);
1240 }
1241 
1242 static void
1243 get_desc(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1244 {
1245  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "desc", ocs->desc);
1246 }
1247 
1248 static void
1249 get_fw_rev(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1250 {
1251  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev", ocs_hal_get_ptr(&ocs->hal, OCS_HAL_FW_REV));
1252 }
1253 
1254 static void
1255 get_fw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1256 {
1257  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "fw_rev2", ocs_hal_get_ptr(&ocs->hal, OCS_HAL_FW_REV2));
1258 }
1259 
1260 static void
1261 get_ipl(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1262 {
1263  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ipl", ocs_hal_get_ptr(&ocs->hal, OCS_HAL_IPL));
1264 }
1265 
1266 static void
1267 get_hw_rev1(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1268 {
1269  uint32_t value;
1270 
1271  ocs_hal_get(&ocs->hal, OCS_HAL_HW_REV1, &value);
1272 
1273  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev1", "%u", value);
1274 }
1275 
1276 static void
1277 get_hw_rev2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1278 {
1279  uint32_t value;
1280 
1281  ocs_hal_get(&ocs->hal, OCS_HAL_HW_REV2, &value);
1282 
1283  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev2", "%u", value);
1284 }
1285 
1286 static void
1287 get_hw_rev3(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1288 {
1289  uint32_t value;
1290  ocs_hal_get(&ocs->hal, OCS_HAL_HW_REV3, &value);
1291 
1292  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_rev3", "%u", value);
1293 }
1294 
1295 static void
1296 get_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1297 {
1298  uint64_t *wwnn;
1299 
1300  wwnn = ocs_hal_get_ptr(&ocs->hal, OCS_HAL_WWN_NODE);
1301 
1302  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwnn", "0x%" PRIx64 , ocs_htobe64(*wwnn));
1303 }
1304 
1305 static void
1306 get_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1307 {
1308  uint64_t *wwpn;
1309 
1310  wwpn = ocs_hal_get_ptr(&ocs->hal, OCS_HAL_WWN_PORT);
1311 
1312  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "wwpn", "0x%" PRIx64 , ocs_htobe64(*wwpn));
1313 }
1314 
1315 static void
1316 get_sn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1317 {
1318  uint8_t *pserial;
1319  uint32_t len;
1320  char sn_buf[256];
1321 
1323  if (pserial) {
1324  len = *pserial ++;
1325  strncpy(sn_buf, (char*)pserial, len);
1326  sn_buf[len] = '\0';
1327  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sn", sn_buf);
1328  }
1329 }
1330 
1331 static void
1332 get_pn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1333 {
1334  uint8_t *pserial;
1335  uint32_t len;
1336  char sn_buf[256];
1337 
1339  if (pserial) {
1340  len = *pserial ++;
1341  strncpy(sn_buf, (char*)pserial, len);
1342  sn_buf[len] = '\0';
1343  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", sn_buf);
1344  } else {
1345  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pn", ocs->model);
1346  }
1347 }
1348 
1349 static void
1350 get_sli4_intf_reg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1351 {
1352 
1353  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "sli4_intf_reg", "0x%04x",
1354  ocs_config_read32(ocs, SLI4_INTF_REG));
1355 }
1356 
1357 static void
1358 get_phy_port_num(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1359 {
1360  uint32_t phy_port;
1361 
1362  phy_port = ocs_scsi_get_property(ocs, OCS_SCSI_PORTNUM);
1363  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "phy_port_num", "0x%04x", phy_port);
1364 }
1365 static void
1366 get_asic_id(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1367 {
1368 
1369  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "asic_id_reg", "0x%04x",
1370  ocs_config_read32(ocs, SLI4_ASIC_ID_REG));
1371 }
1372 
1373 static void
1374 get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1375 {
1376  uint32_t family;
1377  uint32_t asic_id;
1378  uint32_t asic_gen_num;
1379  uint32_t asic_rev_num;
1380  uint32_t rev_id;
1381  char result_buf[80];
1382  char tmp_buf[80];
1383 
1384  family = (ocs_config_read32(ocs, SLI4_INTF_REG) & 0x00000f00) >> 8;
1385  asic_id = ocs_config_read32(ocs, SLI4_ASIC_ID_REG);
1386  asic_rev_num = asic_id & 0xff;
1387  asic_gen_num = (asic_id & 0xff00) >> 8;
1388 
1389  rev_id = ocs_config_read32(ocs, SLI4_PCI_CLASS_REVISION) & 0xff;
1390 
1391  switch(family) {
1392  case 0x00:
1393  // BE2
1394  ocs_strncpy(result_buf, "BE2 A", sizeof(result_buf));
1395  ocs_snprintf(tmp_buf, 2, "%d", rev_id);
1396  strcat(result_buf, tmp_buf);
1397  break;
1398  case 0x01:
1399  // BE3
1400  ocs_strncpy(result_buf, "BE3", sizeof(result_buf));
1401  if (rev_id >= 0x10) {
1402  strcat(result_buf, "-R");
1403  }
1404  ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A');
1405  strcat(result_buf, tmp_buf);
1406  ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
1407  strcat(result_buf, tmp_buf);
1408  break;
1409  case 0x02:
1410  // Skyhawk A0
1411  ocs_strncpy(result_buf, "Skyhawk A0", sizeof(result_buf));
1412  break;
1413  case 0x0a:
1414  // Lancer A0
1415  ocs_strncpy(result_buf, "Lancer A", sizeof(result_buf));
1416  ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
1417  strcat(result_buf, tmp_buf);
1418  break;
1419  case 0x0b:
1420  // Lancer B0 or D0
1421  ocs_strncpy(result_buf, "Lancer", sizeof(result_buf));
1422  ocs_snprintf(tmp_buf, 3, " %c", ((rev_id & 0xf0) >> 4) + 'A');
1423  strcat(result_buf, tmp_buf);
1424  ocs_snprintf(tmp_buf, 2, "%d", rev_id & 0x0f);
1425  strcat(result_buf, tmp_buf);
1426  break;
1427  case 0x0c:
1428  ocs_strncpy(result_buf, "Lancer G6", sizeof(result_buf));
1429  break;
1430  case 0x0d:
1431  ocs_strncpy(result_buf, "Prism", sizeof(result_buf));
1432  break;
1433  case 0x0f:
1434  // Refer to ASIC_ID
1435  switch(asic_gen_num) {
1436  case 0x00:
1437  ocs_strncpy(result_buf, "BE2", sizeof(result_buf));
1438  break;
1439  case 0x03:
1440  ocs_strncpy(result_buf, "BE3-R", sizeof(result_buf));
1441  break;
1442  case 0x04:
1443  ocs_strncpy(result_buf, "Skyhawk-R", sizeof(result_buf));
1444  break;
1445  case 0x05:
1446  ocs_strncpy(result_buf, "Corsair", sizeof(result_buf));
1447  break;
1448  case 0x0b:
1449  ocs_strncpy(result_buf, "Lancer", sizeof(result_buf));
1450  break;
1451  case 0x0c:
1452  ocs_strncpy(result_buf, "LancerG6", sizeof(result_buf));
1453  break;
1454  case 0x0d:
1455  ocs_strncpy(result_buf, "Prism", sizeof(result_buf));
1456  break;
1457  default:
1458  ocs_strncpy(result_buf, "Unknown", sizeof(result_buf));
1459  }
1460  if (ocs_strcmp(result_buf, "Unknown") != 0) {
1461  ocs_snprintf(tmp_buf, 3, " %c", ((asic_rev_num & 0xf0) >> 4) + 'A');
1462  strcat(result_buf, tmp_buf);
1463  ocs_snprintf(tmp_buf, 2, "%d", asic_rev_num & 0x0f);
1464  strcat(result_buf, tmp_buf);
1465  }
1466  break;
1467  default:
1468  ocs_strncpy(result_buf, "Unknown", sizeof(result_buf));
1469  }
1470 
1471  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "chip_type", result_buf);
1472 
1473 }
1474 
1475 static void
1476 get_pci_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1477 {
1478 
1479  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_vendor", "0x%04x", ocs->pci_vendor);
1480 }
1481 
1482 static void
1483 get_pci_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1484 {
1485 
1486  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_device", "0x%04x", ocs->pci_device);
1487 }
1488 
1489 static void
1490 get_pci_subsystem_vendor(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1491 {
1492 
1493  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_vendor", "0x%04x", ocs->pci_subsystem_vendor);
1494 }
1495 
1496 static void
1497 get_pci_subsystem_device(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1498 {
1499 
1500  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "pci_subsystem_device", "0x%04x", ocs->pci_subsystem_device);
1501 }
1502 
1503 static void
1504 get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1505 {
1506  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tgt_rscn_delay", "%ld", ocs->tgt_rscn_delay_msec / 1000);
1507 }
1508 
1509 static void
1510 get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1511 {
1512  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "tgt_rscn_period", "%ld", ocs->tgt_rscn_period_msec / 1000);
1513 }
1514 
1515 static void
1516 get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1517 {
1518  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_cmd", "%d",
1519  (ocs->err_injection == INJECT_DROP_CMD ? 1:0));
1520 }
1521 
1522 static void
1523 get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1524 {
1525  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_free_drop_cmd", "%d",
1526  (ocs->err_injection == INJECT_FREE_DROPPED ? 1:0));
1527 }
1528 
1529 static void
1530 get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1531 {
1532  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_data", "%d",
1533  (ocs->err_injection == INJECT_DROP_DATA ? 1:0));
1534 }
1535 
1536 static void
1537 get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1538 {
1539  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "inject_drop_resp", "%d",
1540  (ocs->err_injection == INJECT_DROP_RESP ? 1:0));
1541 }
1542 
1543 static void
1544 get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1545 {
1546  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "cmd_err_inject", "0x%02x", ocs->cmd_err_inject);
1547 }
1548 
1549 static void
1550 get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1551 {
1552  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "cmd_delay_value", "%ld", ocs->delay_value_msec);
1553 }
1554 
1555 static void
1556 get_businfo(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1557 {
1558  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "businfo", ocs->businfo);
1559 }
1560 
1561 static void
1562 get_lip_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1563 {
1564  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "lip_count", "%d",
1565  ocs->xport? ocs->xport->lip_count: 0);
1566 }
1567 
1568 static void
1569 get_active_xri_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1570 {
1571  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "active_xri_count", "%d",
1573 }
1574 static void
1575 get_active_rpi_count(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1576 {
1577 
1578  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "active_rpi_count", "%d",
1579  ocs_hal_rpi_active_count(&ocs->hal));
1580 }
1581 
1582 static void
1583 get_sfp_a0(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1584 {
1585  uint8_t *page_data;
1586  char *buf;
1587  int i;
1588  int32_t bytes_read;
1589 
1590  page_data = ocs_malloc(ocs, SFP_PAGE_SIZE, OCS_M_ZERO | OCS_M_NOWAIT);
1591  if (page_data == NULL) {
1592  return;
1593  }
1594 
1595  buf = ocs_malloc(ocs, (SFP_PAGE_SIZE * 3) + 1, OCS_M_ZERO | OCS_M_NOWAIT);
1596  if (buf == NULL) {
1597  ocs_free(ocs, page_data, SFP_PAGE_SIZE);
1598  return;
1599  }
1600 
1601  bytes_read = ocs_mgmt_get_sfp(ocs, SFP_PAGE_A0,
1602  page_data, SFP_PAGE_SIZE);
1603  if (bytes_read <= 0) {
1604  if (bytes_read == -ENODEV) {
1605  ocs_log_debug(ocs, "%s: No SFP module present on this device\n", __func__);
1606  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", "no-sfp");
1607  } else {
1608  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", "(unknown)");
1609  }
1610  } else {
1611  char *d = buf;
1612  uint8_t *s = page_data;
1613  int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1;
1614  int bytes_added;
1615 
1616  for (i = 0; i < bytes_read; i++) {
1617  bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s);
1618  ++s;
1619  d += bytes_added;
1620  buffer_remaining -= bytes_added;
1621  }
1622  *d = '\0';
1623  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a0", buf);
1624  }
1625 
1626  ocs_free(ocs, page_data, SFP_PAGE_SIZE);
1627  ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE) + 1);
1628 }
1629 
1630 static void
1631 get_sfp_a2(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1632 {
1633  uint8_t *page_data;
1634  char *buf;
1635  int i;
1636  int32_t bytes_read;
1637 
1638  page_data = ocs_malloc(ocs, SFP_PAGE_SIZE, OCS_M_ZERO | OCS_M_NOWAIT);
1639  if (page_data == NULL) {
1640  return;
1641  }
1642 
1643  buf = ocs_malloc(ocs, (SFP_PAGE_SIZE * 3) + 1, OCS_M_ZERO | OCS_M_NOWAIT);
1644  if (buf == NULL) {
1645  ocs_free(ocs, page_data, SFP_PAGE_SIZE);
1646  return;
1647  }
1648 
1649  bytes_read = ocs_mgmt_get_sfp(ocs, SFP_PAGE_A2,
1650  page_data, SFP_PAGE_SIZE);
1651  if (bytes_read <= 0) {
1652  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", "(unknown)");
1653  } else {
1654  char *d = buf;
1655  uint8_t *s = page_data;
1656  int buffer_remaining = (SFP_PAGE_SIZE * 3) + 1;
1657  int bytes_added;
1658 
1659  for (i=0; i < bytes_read; i++) {
1660  bytes_added = ocs_snprintf(d, buffer_remaining, "%02x ", *s);
1661  ++s;
1662  d += bytes_added;
1663  buffer_remaining -= bytes_added;
1664  }
1665  *d = '\0';
1666  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "sfp_a2", buf);
1667  }
1668 
1669  ocs_free(ocs, page_data, SFP_PAGE_SIZE);
1670  ocs_free(ocs, buf, (3 * SFP_PAGE_SIZE) + 1);
1671 }
1672 
1673 static void
1674 get_fw_dump_present(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1675 {
1676  uint32_t dump_present = FW_DUMP_STATE_NONE;
1677 
1678  ocs_hal_get(&ocs->hal, OCS_HAL_DUMP_PRESENT, &dump_present);
1679  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fw_dump_present", "%d", dump_present);
1680 }
1681 
1682 static void
1683 get_fw_dump_max_size(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1684 {
1685  uint32_t max_dump_size = 0;
1686 
1687  ocs_hal_get(&ocs->hal, OCS_HAL_DUMP_MAX_SIZE, &max_dump_size);
1688  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "fw_dump_max_size", "%d", max_dump_size);
1689 }
1690 
1691 static void
1692 get_debug_mq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1693 {
1694 
1695  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_mq_dump",
1697 }
1698 
1699 static void
1700 get_debug_cq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1701 {
1702 
1703  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_cq_dump",
1705 }
1706 
1707 static void
1708 get_debug_wq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1709 {
1710  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_wq_dump",
1712 }
1713 
1714 static void
1715 get_debug_eq_dump(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1716 {
1717  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RW, "debug_eq_dump",
1719 }
1720 
1721 static void
1722 get_logmask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1723 {
1724 
1725  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "logmask", "0x%02x", ocs->logmask);
1726 
1727 }
1728 
1729 static void
1730 get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1731 {
1732 
1733  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "loglevel", "%d", loglevel);
1734 
1735 }
1736 
1737 static void
1738 get_current_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1739 {
1740  uint32_t value;
1741 
1742  ocs_hal_get(&(ocs->hal), OCS_HAL_LINK_SPEED, &value);
1743 
1744  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "current_speed", "%d", value);
1745 }
1746 
1747 static void
1748 get_configured_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1749 {
1750  uint32_t value;
1751 
1752  ocs_hal_get(&(ocs->hal), OCS_HAL_LINK_CONFIG_SPEED, &value);
1753  if (value == 0) {
1754  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_speed", "auto");
1755  } else {
1756  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "configured_speed", "%d", value);
1757  }
1758 
1759 }
1760 
1761 static void
1762 get_current_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1763 {
1764  uint32_t value;
1765 
1766  ocs_hal_get(&(ocs->hal), OCS_HAL_TOPOLOGY, &value);
1767  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "current_topology", "%d", value);
1768 
1769 }
1770 
1771 static void
1772 get_configured_topology(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1773 {
1774  uint32_t value;
1775 
1776  ocs_hal_get(&(ocs->hal), OCS_HAL_CONFIG_TOPOLOGY, &value);
1777  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "configured_topology", "%d", value);
1778 
1779 }
1780 
1781 static void
1782 get_current_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1783 {
1784  ocs_xport_stats_t value;
1785 
1786  if (ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &value) == 0) {
1787  if (value.value == OCS_XPORT_PORT_ONLINE) {
1788  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_link_state", "online");
1789  } else {
1790  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "current_link_state", "offline");
1791  }
1792  }
1793 }
1794 
1795 static void
1796 get_logical_link_speed(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1797 {
1798  ocs_xport_stats_t value;
1799 
1800  ocs_xport_status(ocs->xport, OCS_XPORT_LOGICAL_LINK_SPEED, &value);
1801 
1802  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "logical_link_speed", "%d", value.value);
1803 }
1804 
1805 static void
1806 get_configured_link_state(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1807 {
1808  ocs_xport_stats_t value;
1809 
1810  if (ocs_xport_status(ocs->xport, OCS_XPORT_CONFIG_PORT_STATUS, &value) == 0) {
1811  if (value.value == OCS_XPORT_PORT_ONLINE) {
1812  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_link_state", "online");
1813  } else {
1814  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "configured_link_state", "offline");
1815  }
1816  }
1817 }
1818 
1819 #if defined(ENABLE_FABRIC_EMULATION)
1820 static void
1821 get_femul_enable(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1822 {
1823  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "femul_enable", "%d",
1824  (ocs->ctrlmask & OCS_CTRLMASK_ENABLE_FABRIC_EMULATION) != 0);
1825 }
1826 #endif
1827 
1828 /**
1829  * @brief HAL link config enum to mgmt string value mapping.
1830  *
1831  * This structure provides a mapping from the ocs_hal_linkcfg_e
1832  * enum (enum exposed for the OCS_HAL_PORT_SET_LINK_CONFIG port
1833  * control) to the mgmt string that is passed in by the mgmt application
1834  * (elxsdkutil).
1835  */
1836 typedef struct ocs_mgmt_linkcfg_map_s {
1838  const char *mgmt_str;
1840 
1849 
1850 /**
1851  * @brief Get the HAL linkcfg enum from the mgmt config string.
1852  *
1853  * @param mgmt_str mgmt string value.
1854  *
1855  * @return Returns the HAL linkcfg enum corresponding to clp_str.
1856  */
1857 static ocs_hal_linkcfg_e
1858 ocs_hal_linkcfg_from_mgmt(const char *mgmt_str)
1859 {
1860  uint32_t i;
1861  for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) {
1862  if (ocs_strncmp(mgmt_linkcfg_map[i].mgmt_str,
1863  mgmt_str, ocs_strlen(mgmt_str)) == 0) {
1864  return mgmt_linkcfg_map[i].linkcfg;
1865  }
1866  }
1867  return OCS_HAL_LINKCFG_NA;
1868 }
1869 
1870 /**
1871  * @brief Get the mgmt string value from the HAL linkcfg enum.
1872  *
1873  * @param linkcfg HAL linkcfg enum.
1874  *
1875  * @return Returns the mgmt string value corresponding to the given HAL linkcfg.
1876  */
1877 static const char *
1879 {
1880  uint32_t i;
1881  for (i = 0; i < ARRAY_SIZE(mgmt_linkcfg_map); i++) {
1882  if (mgmt_linkcfg_map[i].linkcfg == linkcfg) {
1883  return mgmt_linkcfg_map[i].mgmt_str;
1884  }
1885  }
1887 }
1888 
1889 /**
1890  * @brief Link configuration callback argument
1891  */
1892 typedef struct ocs_mgmt_linkcfg_arg_s {
1893  ocs_sem_t semaphore;
1894  int32_t status;
1897 
1898 /**
1899  * @brief Get linkcfg config value
1900  *
1901  * @param ocs Pointer to the ocs structure.
1902  * @param name Not used.
1903  * @param textbuf The textbuf to which the result is written.
1904  *
1905  * @return None.
1906  */
1907 static void
1908 get_linkcfg(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1909 {
1910  const char *linkcfg_str = NULL;
1911  uint32_t value;
1912  ocs_hal_linkcfg_e linkcfg;
1913  ocs_hal_get(&ocs->hal, OCS_HAL_LINKCFG, &value);
1914  linkcfg = (ocs_hal_linkcfg_e)value;
1915  linkcfg_str = ocs_mgmt_from_hal_linkcfg(linkcfg);
1916  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "linkcfg", linkcfg_str);
1917 }
1918 
1919 /**
1920  * @brief Get requested WWNN config value
1921  *
1922  * @param ocs Pointer to the ocs structure.
1923  * @param name Not used.
1924  * @param textbuf The textbuf to which the result is written.
1925  *
1926  * @return None.
1927  */
1928 static void
1929 get_req_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1930 {
1931  ocs_xport_t *xport = ocs->xport;
1932 
1933  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "requested_wwnn", "0x%" PRIx64 , xport->req_wwnn);
1934 }
1935 
1936 /**
1937  * @brief Get requested WWPN config value
1938  *
1939  * @param ocs Pointer to the ocs structure.
1940  * @param name Not used.
1941  * @param textbuf The textbuf to which the result is written.
1942  *
1943  * @return None.
1944  */
1945 static void
1946 get_req_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1947 {
1948  ocs_xport_t *xport = ocs->xport;
1949 
1950  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "requested_wwpn", "0x%" PRIx64 , xport->req_wwpn);
1951 }
1952 
1953 /**
1954  * @brief Get requested nodedb_mask config value
1955  *
1956  * @param ocs Pointer to the ocs structure.
1957  * @param name Not used.
1958  * @param textbuf The textbuf to which the result is written.
1959  *
1960  * @return None.
1961  */
1962 static void
1963 get_nodedb_mask(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
1964 {
1965  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RW, "nodedb_mask", "0x%08x", ocs->nodedb_mask);
1966 }
1967 
1968 /**
1969  * @brief Set requested WWNN value.
1970  *
1971  * @param ocs Pointer to the ocs structure.
1972  * @param name Not used.
1973  * @param value Value to which the linkcfg is set.
1974  *
1975  * @return Returns 0 on success.
1976  */
1977 
1978 static int
1979 set_req_wwnn(ocs_t *ocs, char *name, char *value)
1980 {
1981  int rc;
1982  uint64_t wwnn;
1983 
1984  if (ocs_strcasecmp(value, "default") == 0) {
1985  wwnn = 0;
1986  }
1987  else if (parse_wwn(value, &wwnn) != 0) {
1988  ocs_log_test(ocs, "Invalid WWNN: %s\n", value);
1989  return -1;
1990  }
1991 
1992  rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWNN_SET, wwnn);
1993 
1994  if(rc) {
1995  ocs_log_test(ocs, "OCS_XPORT_WWNN_SET failed: %d\n", rc);
1996  }
1997 
1998  return rc;
1999 }
2000 
2001 /**
2002  * @brief Set requested WWNP value.
2003  *
2004  * @param ocs Pointer to the ocs structure.
2005  * @param name Not used.
2006  * @param value Value to which the linkcfg is set.
2007  *
2008  * @return Returns 0 on success.
2009  */
2010 
2011 static int
2012 set_req_wwpn(ocs_t *ocs, char *name, char *value)
2013 {
2014  int rc;
2015  uint64_t wwpn;
2016 
2017  if (ocs_strcasecmp(value, "default") == 0) {
2018  wwpn = 0;
2019  }
2020  else if (parse_wwn(value, &wwpn) != 0) {
2021  ocs_log_test(ocs, "Invalid WWPN: %s\n", value);
2022  return -1;
2023  }
2024 
2025  rc = ocs_xport_control(ocs->xport, OCS_XPORT_WWPN_SET, wwpn);
2026 
2027  if(rc) {
2028  ocs_log_test(ocs, "OCS_XPORT_WWPN_SET failed: %d\n", rc);
2029  }
2030 
2031  return rc;
2032 }
2033 
2034 /**
2035  * @brief Set node debug mask value
2036  *
2037  * @param ocs Pointer to the ocs structure.
2038  * @param name Not used.
2039  * @param value Value to which the nodedb_mask is set.
2040  *
2041  * @return Returns 0 on success.
2042  */
2043 static int
2044 set_nodedb_mask(ocs_t *ocs, char *name, char *value)
2045 {
2046  ocs->nodedb_mask = ocs_strtoul(value, 0, 0);
2047  return 0;
2048 }
2049 
2050 /**
2051  * @brief Set linkcfg config value.
2052  *
2053  * @param ocs Pointer to the ocs structure.
2054  * @param name Not used.
2055  * @param value Value to which the linkcfg is set.
2056  *
2057  * @return Returns 0 on success.
2058  */
2059 static int
2060 set_linkcfg(ocs_t *ocs, char *name, char *value)
2061 {
2062  ocs_hal_linkcfg_e linkcfg;
2063  ocs_mgmt_linkcfg_arg_t cb_arg;
2064  ocs_hal_rtn_e status;
2065 
2066  ocs_sem_init(&cb_arg.semaphore, 0, "mgmt_linkcfg");
2067 
2068  /* translate mgmt linkcfg string to HAL linkcfg enum */
2069  linkcfg = ocs_hal_linkcfg_from_mgmt(value);
2070 
2071  /* set HAL linkcfg */
2073  (uintptr_t)linkcfg, ocs_mgmt_linkcfg_cb, &cb_arg);
2074  if (status) {
2075  ocs_log_test(ocs, "ocs_hal_set_linkcfg failed\n");
2076  return -1;
2077  }
2078 
2079  if (ocs_sem_p(&cb_arg.semaphore, OCS_SEM_FOREVER)) {
2080  ocs_log_err(ocs, "ocs_sem_p failed\n");
2081  return -1;
2082  }
2083 
2084  if (cb_arg.status) {
2085  ocs_log_test(ocs, "failed to set linkcfg from HAL status=%d\n",
2086  cb_arg.status);
2087  return -1;
2088  }
2089 
2090  return 0;
2091 }
2092 
2093 /**
2094  * @brief Linkcfg callback
2095  *
2096  * @param status Result of the linkcfg get/set operation.
2097  * @param value Resulting linkcfg value.
2098  * @param arg Callback argument.
2099  *
2100  * @return None.
2101  */
2102 static void
2103 ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg)
2104 {
2106  cb_arg->status = status;
2107  cb_arg->linkcfg = (ocs_hal_linkcfg_e)value;
2108  ocs_sem_v(&cb_arg->semaphore);
2109 }
2110 
2111 static int
2112 set_debug_mq_dump(ocs_t *ocs, char *name, char *value)
2113 {
2114  int result;
2115 
2116  if (ocs_strcasecmp(value, "false") == 0) {
2118  result = 0;
2119  } else if (ocs_strcasecmp(value, "true") == 0) {
2121  result = 0;
2122  } else {
2123  result = -1;
2124  }
2125 
2126  return result;
2127 }
2128 
2129 static int
2130 set_debug_cq_dump(ocs_t *ocs, char *name, char *value)
2131 {
2132  int result;
2133 
2134  if (ocs_strcasecmp(value, "false") == 0) {
2136  result = 0;
2137  } else if (ocs_strcasecmp(value, "true") == 0) {
2139  result = 0;
2140  } else {
2141  result = -1;
2142  }
2143 
2144  return result;
2145 }
2146 
2147 static int
2148 set_debug_wq_dump(ocs_t *ocs, char *name, char *value)
2149 {
2150  int result;
2151 
2152  if (ocs_strcasecmp(value, "false") == 0) {
2154  result = 0;
2155  } else if (ocs_strcasecmp(value, "true") == 0) {
2157  result = 0;
2158  } else {
2159  result = -1;
2160  }
2161 
2162  return result;
2163 }
2164 
2165 static int
2166 set_debug_eq_dump(ocs_t *ocs, char *name, char *value)
2167 {
2168  int result;
2169 
2170  if (ocs_strcasecmp(value, "false") == 0) {
2172  result = 0;
2173  } else if (ocs_strcasecmp(value, "true") == 0) {
2175  result = 0;
2176  } else {
2177  result = -1;
2178  }
2179 
2180  return result;
2181 }
2182 
2183 static int
2184 set_logmask(ocs_t *ocs, char *name, char *value)
2185 {
2186 
2187  ocs->logmask = ocs_strtoul(value, NULL, 0);
2188 
2189  return 0;
2190 }
2191 
2192 static int
2193 set_loglevel(ocs_t *ocs, char *name, char *value)
2194 {
2195 
2196  loglevel = ocs_strtoul(value, NULL, 0);
2197 
2198  return 0;
2199 }
2200 
2201 static int
2202 set_configured_speed(ocs_t *ocs, char *name, char *value)
2203 {
2204  int result = 0;
2205  ocs_hal_rtn_e hal_rc;
2206  int xport_rc;
2207  uint32_t spd;
2208 
2209  spd = ocs_strtoul(value, NULL, 0);
2210 
2211  ocs_log_debug(ocs, "Taking port offline\n");
2212  xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
2213  if (xport_rc != 0) {
2214  ocs_log_test(ocs, "Port offline failed\n");
2215  result = -1;
2216  } else {
2217  ocs_log_debug(ocs, "Setting port to speed %d\n", spd);
2218  hal_rc = ocs_hal_set(&ocs->hal, OCS_HAL_LINK_SPEED, spd);
2219  if (hal_rc != OCS_HAL_RTN_SUCCESS) {
2220  ocs_log_test(ocs, "Speed set failed\n");
2221  result = -1;
2222  }
2223 
2224  // If we failed to set the speed we still want to try to bring
2225  // the port back online
2226 
2227  ocs_log_debug(ocs, "Bringing port online\n");
2228  xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
2229  if (xport_rc != 0) {
2230  result = -1;
2231  }
2232  }
2233 
2234  return result;
2235 }
2236 
2237 static int
2238 set_configured_topology(ocs_t *ocs, char *name, char *value)
2239 {
2240  int result = 0;
2241  ocs_hal_rtn_e hal_rc;
2242  int xport_rc;
2243  uint32_t topo;
2244 
2245  topo = ocs_strtoul(value, NULL, 0);
2246  if (topo >= OCS_HAL_TOPOLOGY_MAX) {
2247  return -1;
2248  }
2249 
2250  ocs_log_debug(ocs, "Taking port offline\n");
2251  xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
2252  if (xport_rc != 0) {
2253  ocs_log_test(ocs, "Port offline failed\n");
2254  result = -1;
2255  } else {
2256  ocs_log_debug(ocs, "Setting port to topology %d\n", topo);
2257  hal_rc = ocs_hal_set(&ocs->hal, OCS_HAL_TOPOLOGY, topo);
2258  if (hal_rc != OCS_HAL_RTN_SUCCESS) {
2259  ocs_log_test(ocs, "Topology set failed\n");
2260  result = -1;
2261  }
2262 
2263  // If we failed to set the topology we still want to try to bring
2264  // the port back online
2265 
2266  ocs_log_debug(ocs, "Bringing port online\n");
2267  xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
2268  if (xport_rc != 0) {
2269  result = -1;
2270  }
2271  }
2272 
2273  return result;
2274 }
2275 
2276 static int
2277 set_configured_link_state(ocs_t *ocs, char *name, char *value)
2278 {
2279  int result = 0;
2280  int xport_rc;
2281 
2282  if (ocs_strcasecmp(value, "offline") == 0) {
2283  ocs_log_debug(ocs, "Setting port to %s\n", value);
2284  xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_OFFLINE);
2285  if (xport_rc != 0) {
2286  ocs_log_test(ocs, "Setting port to offline failed\n");
2287  result = -1;
2288  }
2289  } else if (ocs_strcasecmp(value, "online") == 0) {
2290  ocs_log_debug(ocs, "Setting port to %s\n", value);
2291  xport_rc = ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE);
2292  if (xport_rc != 0) {
2293  ocs_log_test(ocs, "Setting port to online failed\n");
2294  result = -1;
2295  }
2296  } else {
2297  ocs_log_test(ocs, "Unsupported link state \"%s\"\n", value);
2298  result = -1;
2299  }
2300 
2301  return result;
2302 }
2303 
2304 #if defined(ENABLE_FABRIC_EMULATION)
2305 static int
2306 set_femul_enable(ocs_t *ocs, char *name, char *value)
2307 {
2308  if (ocs_strtoul(value, 0, 0) != 0) {
2309  ocs->ctrlmask |= OCS_CTRLMASK_ENABLE_FABRIC_EMULATION;
2310  } else {
2311  ocs->ctrlmask &= ~OCS_CTRLMASK_ENABLE_FABRIC_EMULATION;
2312  }
2313  return 0;
2314 }
2315 #endif
2316 
2317 typedef struct ocs_mgmt_get_port_protocol_result {
2318  ocs_sem_t semaphore;
2319  int32_t status;
2322 
2323 
2324 static void
2326  ocs_hal_port_protocol_e port_protocol,
2327  void *arg)
2328 {
2330 
2331  result->status = status;
2332  result->port_protocol = port_protocol;
2333 
2334  ocs_sem_v(&(result->semaphore));
2335 }
2336 
2337 static void
2338 get_port_protocol(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2339 {
2341  uint8_t bus;
2342  uint8_t dev;
2343  uint8_t func;
2344 
2345  ocs_sem_init(&(result.semaphore), 0, "get_port_protocol");
2346 
2347  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
2348 
2350  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2351  // Undefined failure
2352  ocs_log_err(ocs, "ocs_sem_p failed\n");
2353  return;
2354  }
2355  if (result.status == 0) {
2356  switch (result.port_protocol) {
2358  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "iSCSI");
2359  break;
2361  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FCoE");
2362  break;
2364  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "FC");
2365  break;
2367  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Other");
2368  break;
2369  }
2370  } else {
2371  ocs_log_test(ocs, "getting port profile status 0x%x\n", result.status);
2372  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "port_protocol", "Unknown");
2373  }
2374  }
2375 }
2376 
2377 typedef struct ocs_mgmt_set_port_protocol_result {
2378  ocs_sem_t semaphore;
2379  int32_t status;
2381 
2382 
2383 
2384 static void
2386  void *arg)
2387 {
2389 
2390  result->status = status;
2391 
2392  ocs_sem_v(&(result->semaphore));
2393 }
2394 
2395 /**
2396  * @brief Set port protocol
2397  * @par Description
2398  * This is a management action handler to set the current
2399  * port protocol. Input value should be one of iSCSI,
2400  * FC, or FCoE.
2401  *
2402  * @param ocs Pointer to the ocs structure.
2403  * @param name Name of the action being performed.
2404  * @param value The value to be assigned
2405  *
2406  * @return Returns 0 on success, non-zero on failure.
2407  */
2408 static int32_t
2409 set_port_protocol(ocs_t *ocs, char *name, char *value)
2410 {
2412  int32_t rc = 0;
2413  ocs_hal_port_protocol_e new_protocol;
2414  uint8_t bus;
2415  uint8_t dev;
2416  uint8_t func;
2417 
2418  ocs_get_bus_dev_func(ocs, &bus, &dev, &func);
2419 
2420  ocs_sem_init(&(result.semaphore), 0, "set_port_protocol");
2421 
2422  if (ocs_strcasecmp(value, "iscsi") == 0) {
2423  new_protocol = OCS_HAL_PORT_PROTOCOL_ISCSI;
2424  } else if (ocs_strcasecmp(value, "fc") == 0) {
2425  new_protocol = OCS_HAL_PORT_PROTOCOL_FC;
2426  } else if (ocs_strcasecmp(value, "fcoe") == 0) {
2427  new_protocol = OCS_HAL_PORT_PROTOCOL_FCOE;
2428  } else {
2429  return -1;
2430  }
2431 
2432  rc = ocs_hal_set_port_protocol(&ocs->hal, new_protocol, func,
2434  if (rc == OCS_HAL_RTN_SUCCESS) {
2435  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2436  // Undefined failure
2437  ocs_log_err(ocs, "ocs_sem_p failed\n");
2438  return -ENXIO;
2439  }
2440  if (result.status == 0) {
2441  // Success.
2442  rc = 0;
2443  } else {
2444  rc = -1;
2445  ocs_log_test(ocs, "setting active profile status 0x%x\n",
2446  result.status);
2447  }
2448  }
2449 
2450  return rc;
2451 }
2452 
2453 typedef struct ocs_mgmt_get_profile_list_result_s {
2454  ocs_sem_t semaphore;
2455  int32_t status;
2458 
2459 static void
2460 ocs_mgmt_get_profile_list_cb(int32_t status, ocs_hal_profile_list_t *list, void *ul_arg)
2461 {
2462  ocs_mgmt_get_profile_list_result_t *result = ul_arg;
2463 
2464  result->status = status;
2465  result->list = list;
2466 
2467  ocs_sem_v(&(result->semaphore));
2468 }
2469 
2470 /**
2471  * @brief Get list of profiles
2472  * @par Description
2473  * This is a management action handler to get the list of
2474  * profiles supported by the SLI port. Although the spec says
2475  * that all SLI platforms support this, only Skyhawk actually
2476  * has a useful implementation.
2477  *
2478  * @param ocs Pointer to the ocs structure.
2479  * @param name Name of the action being performed.
2480  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2481  *
2482  * @return none
2483  */
2484 static void
2485 get_profile_list(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2486 {
2488 
2489  ocs_sem_init(&(result.semaphore), 0, "get_profile_list");
2490 
2492  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2493  // Undefined failure
2494  ocs_log_err(ocs, "ocs_sem_p failed\n");
2495  return;
2496  }
2497  if (result.status == 0) {
2498  // Success.
2499 #define MAX_LINE_SIZE 520
2500 #define BUFFER_SIZE MAX_LINE_SIZE*40
2501  char *result_buf;
2502  char result_line[MAX_LINE_SIZE];
2503  uint32_t bytes_left;
2504  uint32_t i;
2505 
2506  result_buf = ocs_malloc(ocs, BUFFER_SIZE, OCS_M_ZERO);
2507  bytes_left = BUFFER_SIZE;
2508 
2509  for (i=0; i<result.list->num_descriptors; i++) {
2510  sprintf(result_line, "0x%02x:%s\n", result.list->descriptors[i].profile_id,
2511  result.list->descriptors[i].profile_description);
2512  if (strlen(result_line) < bytes_left) {
2513  strcat(result_buf, result_line);
2514  bytes_left -= strlen(result_line);
2515  }
2516  }
2517 
2518 
2519  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "profile_list", result_buf);
2520 
2521  ocs_free(ocs, result_buf, BUFFER_SIZE);
2522  ocs_free(ocs, result.list, sizeof(ocs_hal_profile_list_t));
2523  } else {
2524  ocs_log_test(ocs, "getting profile list status 0x%x\n", result.status);
2525  }
2526  }
2527 }
2528 
2529 typedef struct ocs_mgmt_get_active_profile_result {
2530  ocs_sem_t semaphore;
2531  int32_t status;
2534 
2535 static void
2536 ocs_mgmt_get_active_profile_cb(int32_t status, uint32_t active_profile, void *ul_arg)
2537 {
2538  ocs_mgmt_get_active_profile_result_t *result = ul_arg;
2539 
2540  result->status = status;
2541  result->active_profile_id = active_profile;
2542 
2543  ocs_sem_v(&(result->semaphore));
2544 }
2545 
2546 #define MAX_PROFILE_LENGTH 5
2547 
2548 /**
2549  * @brief Get active profile
2550  * @par Description
2551  * This is a management action handler to get the currently
2552  * active profile for an SLI port. Although the spec says that
2553  * all SLI platforms support this, only Skyhawk actually has a
2554  * useful implementation.
2555  *
2556  * @param ocs Pointer to the ocs structure.
2557  * @param name Name of the action being performed.
2558  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2559  *
2560  * @return none
2561  */
2562 static void
2563 get_active_profile(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2564 {
2565  char result_string[MAX_PROFILE_LENGTH];
2567 
2568  ocs_sem_init(&(result.semaphore), 0, "get_active_profile");
2569 
2571  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2572  // Undefined failure
2573  ocs_log_err(ocs, "ocs_sem_p failed\n");
2574  return;
2575  }
2576  if (result.status == 0) {
2577  // Success.
2578  sprintf(result_string, "0x%02x", result.active_profile_id);
2579  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "active_profile", result_string);
2580  } else {
2581  ocs_log_test(ocs, "getting active profile status 0x%x\n", result.status);
2582  }
2583  }
2584 }
2585 
2586 typedef struct ocs_mgmt_set_active_profile_result {
2587  ocs_sem_t semaphore;
2588  int32_t status;
2590 
2591 
2592 static void
2593 ocs_mgmt_set_active_profile_cb(int32_t status, void *ul_arg)
2594 {
2595  ocs_mgmt_get_profile_list_result_t *result = ul_arg;
2596 
2597  result->status = status;
2598 
2599  ocs_sem_v(&(result->semaphore));
2600 }
2601 
2602 /**
2603  * @brief Set active profile
2604  * @par Description
2605  * This is a management action handler to set the currently
2606  * active profile for an SLI port. Although the spec says that
2607  * all SLI platforms support this, only Skyhawk actually has a
2608  * useful implementation.
2609  *
2610  * @param ocs Pointer to the ocs structure.
2611  * @param name Name of the action being performed.
2612  * @param value Requested new value of the property.
2613  *
2614  * @return Returns 0 on success, non-zero on failure.
2615  */
2616 static int32_t
2617 set_active_profile(ocs_t *ocs, char *name, char *value)
2618 {
2620  int32_t rc = 0;
2621  int32_t new_profile;
2622 
2623  new_profile = ocs_strtoul(value, NULL, 0);
2624 
2625  ocs_sem_init(&(result.semaphore), 0, "set_active_profile");
2626 
2627  rc = ocs_hal_set_active_profile(&ocs->hal, ocs_mgmt_set_active_profile_cb, new_profile, &result);
2628  if (rc == OCS_HAL_RTN_SUCCESS) {
2629  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2630  // Undefined failure
2631  ocs_log_err(ocs, "ocs_sem_p failed\n");
2632  return -ENXIO;
2633  }
2634  if (result.status == 0) {
2635  // Success.
2636  rc = 0;
2637  } else {
2638  rc = -1;
2639  ocs_log_test(ocs, "setting active profile status 0x%x\n", result.status);
2640  }
2641  }
2642 
2643  return rc;
2644 }
2645 
2646 typedef struct ocs_mgmt_get_nvparms_result {
2647  ocs_sem_t semaphore;
2648  int32_t status;
2649  uint8_t wwpn[8];
2650  uint8_t wwnn[8];
2651  uint8_t hard_alpa;
2652  uint32_t preferred_d_id;
2654 
2655 static void
2656 ocs_mgmt_get_nvparms_cb(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
2657  uint32_t preferred_d_id, void *ul_arg)
2658 {
2659  ocs_mgmt_get_nvparms_result_t *result = ul_arg;
2660 
2661  result->status = status;
2662  ocs_memcpy(result->wwpn, wwpn, sizeof(result->wwpn));
2663  ocs_memcpy(result->wwnn, wwnn, sizeof(result->wwnn));
2664  result->hard_alpa = hard_alpa;
2665  result->preferred_d_id = preferred_d_id;
2666 
2667  ocs_sem_v(&(result->semaphore));
2668 }
2669 
2670 /**
2671  * @brief Get wwpn
2672  * @par Description
2673  *
2674  *
2675  * @param ocs Pointer to the ocs structure.
2676  * @param name Name of the action being performed.
2677  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2678  *
2679  * @return none
2680  */
2681 static void
2682 get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2683 {
2684  char result_string[24];
2685  static ocs_mgmt_get_nvparms_result_t result;
2686 
2687  ocs_sem_init(&(result.semaphore), 0, "get_nv_wwpn");
2688 
2690  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2691  // Undefined failure
2692  ocs_log_err(ocs, "ocs_sem_p failed\n");
2693  return;
2694  }
2695  if (result.status == 0) {
2696  // Success. Copy wwpn from result struct to result string
2697  sprintf(result_string, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
2698  result.wwpn[0], result.wwpn[1], result.wwpn[2],
2699  result.wwpn[3], result.wwpn[4], result.wwpn[5],
2700  result.wwpn[6], result.wwpn[7]);
2701  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "nv_wwpn", result_string);
2702  } else {
2703  ocs_log_test(ocs, "getting wwpn status 0x%x\n", result.status);
2704  }
2705  }
2706 }
2707 
2708 /**
2709  * @brief Get wwnn
2710  * @par Description
2711  *
2712  *
2713  * @param ocs Pointer to the ocs structure.
2714  * @param name Name of the action being performed.
2715  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2716  *
2717  * @return none
2718  */
2719 static void
2720 get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2721 {
2722  char result_string[24];
2723  static ocs_mgmt_get_nvparms_result_t result;
2724 
2725  ocs_sem_init(&(result.semaphore), 0, "get_nv_wwnn");
2726 
2728  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2729  // Undefined failure
2730  ocs_log_err(ocs, "ocs_sem_p failed\n");
2731  return;
2732  }
2733  if (result.status == 0) {
2734  // Success. Copy wwnn from result struct to result string
2735  ocs_snprintf(result_string, sizeof(result_string), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
2736  result.wwnn[0], result.wwnn[1], result.wwnn[2],
2737  result.wwnn[3], result.wwnn[4], result.wwnn[5],
2738  result.wwnn[6], result.wwnn[7]);
2739  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RW, "nv_wwnn", result_string);
2740  } else {
2741  ocs_log_test(ocs, "getting wwnn status 0x%x\n", result.status);
2742  }
2743  }
2744 }
2745 
2746 /**
2747  * @brief Get accumulated node abort counts
2748  * @par Description Get the sum of all nodes abort count.
2749  *
2750  * @param ocs Pointer to the ocs structure.
2751  * @param name Name of the action being performed.
2752  * @param textbuf Pointer to an ocs_textbuf, which is used to return the results.
2753  *
2754  * @return None.
2755  */
2756 static void
2757 get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
2758 {
2759  uint32_t abort_counts = 0;
2760  ocs_domain_t *domain;
2761  ocs_sport_t *sport;
2762  ocs_node_t *node;
2763 
2764  if (ocs_device_lock_try(ocs) != TRUE) {
2765  /* Didn't get the lock */
2766  return;
2767  }
2768 
2769  /* Here the Device lock is held */
2770  ocs_list_foreach(&ocs->domain_list, domain) {
2771  if (ocs_domain_lock_try(domain) != TRUE) {
2772  /* Didn't get the lock */
2773  ocs_device_unlock(ocs);
2774  return;
2775  }
2776 
2777  /* Here the Domain lock is held */
2778  ocs_list_foreach(&domain->sport_list, sport) {
2779  if (ocs_sport_lock_try(sport) != TRUE) {
2780  /* Didn't get the lock */
2781  ocs_domain_unlock(domain);
2782  ocs_device_unlock(ocs);
2783  return;
2784  }
2785 
2786  /* Here the sport lock is held */
2787  ocs_list_foreach(&sport->node_list, node) {
2788  abort_counts += node->abort_cnt;
2789  }
2790 
2791  ocs_sport_unlock(sport);
2792  }
2793 
2794  ocs_domain_unlock(domain);
2795  }
2796 
2797  ocs_device_unlock(ocs);
2798 
2799  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "node_abort_cnt", "%d" , abort_counts);
2800 }
2801 
2802 typedef struct ocs_mgmt_set_nvparms_result {
2803  ocs_sem_t semaphore;
2804  int32_t status;
2806 
2807 
2808 static void
2809 ocs_mgmt_set_nvparms_cb(int32_t status, void *ul_arg)
2810 {
2811  ocs_mgmt_get_profile_list_result_t *result = ul_arg;
2812 
2813  result->status = status;
2814 
2815  ocs_sem_v(&(result->semaphore));
2816 }
2817 
2818 /**
2819  * @brief Set wwn
2820  * @par Description Sets the Non-volatile worldwide names,
2821  * if provided.
2822  *
2823  * @param ocs Pointer to the ocs structure.
2824  * @param name Name of the action being performed.
2825  * @param wwn_p Requested new WWN values.
2826  *
2827  * @return Returns 0 on success, non-zero on failure.
2828  */
2829 static int32_t
2830 set_nv_wwn(ocs_t *ocs, char *name, char *wwn_p)
2831 {
2833  uint8_t new_wwpn[8];
2834  uint8_t new_wwnn[8];
2835  char *wwpn_p = NULL;
2836  char *wwnn_p = NULL;
2837  int32_t rc = -1;
2838  int wwpn = 0;
2839  int wwnn = 0;
2840  int i;
2841 
2842  /* This is a read-modify-write operation, so first we have to read
2843  * the current values
2844  */
2845  ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn1");
2846 
2847  rc = ocs_hal_get_nvparms(&ocs->hal, ocs_mgmt_get_nvparms_cb, &result);
2848 
2849  if (rc == OCS_HAL_RTN_SUCCESS) {
2850  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2851  /* Undefined failure */
2852  ocs_log_err(ocs, "ocs_sem_p failed\n");
2853  return -ENXIO;
2854  }
2855  if (result.status != 0) {
2856  ocs_log_test(ocs, "getting nvparms status 0x%x\n", result.status);
2857  return -1;
2858  }
2859  }
2860 
2861  /* wwn_p contains wwpn_p@wwnn_p values */
2862  if (wwn_p != NULL) {
2863  wwpn_p = ocs_strsep(&wwn_p, "@");
2864  wwnn_p = wwn_p;
2865  }
2866 
2867  if (wwpn_p != NULL) {
2868  wwpn = ocs_strcmp(wwpn_p, "NA");
2869  }
2870 
2871  if (wwnn_p != NULL) {
2872  wwnn = ocs_strcmp(wwnn_p, "NA");
2873  }
2874 
2875  /* Parse the new WWPN */
2876  if (wwpn != 0) {
2877  if (ocs_sscanf(wwpn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
2878  &(new_wwpn[0]), &(new_wwpn[1]), &(new_wwpn[2]),
2879  &(new_wwpn[3]), &(new_wwpn[4]), &(new_wwpn[5]),
2880  &(new_wwpn[6]), &(new_wwpn[7])) != 8) {
2881  ocs_log_test(ocs, "can't parse WWPN %s\n", wwpn_p);
2882  return -1;
2883  }
2884  }
2885 
2886  /* Parse the new WWNN */
2887  if (wwnn != 0) {
2888  if (ocs_sscanf(wwnn_p, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
2889  &(new_wwnn[0]), &(new_wwnn[1]), &(new_wwnn[2]),
2890  &(new_wwnn[3]), &(new_wwnn[4]), &(new_wwnn[5]),
2891  &(new_wwnn[6]), &(new_wwnn[7])) != 8) {
2892  ocs_log_test(ocs, "can't parse WWNN %s\n", wwnn_p);
2893  return -1;
2894  }
2895  }
2896 
2897  for (i = 0; i < 8; i++) {
2898  /* Use active wwpn, if new one is not provided */
2899  if (wwpn == 0) {
2900  new_wwpn[i] = result.wwpn[i];
2901  }
2902 
2903  /* Use active wwnn, if new one is not provided */
2904  if (wwnn == 0) {
2905  new_wwnn[i] = result.wwnn[i];
2906  }
2907  }
2908 
2909  /* Modify the nv_wwnn and nv_wwpn, then write it back */
2910  ocs_sem_init(&(result.semaphore), 0, "set_nv_wwn2");
2911 
2912  rc = ocs_hal_set_nvparms(&ocs->hal, ocs_mgmt_set_nvparms_cb, new_wwpn,
2913  new_wwnn, result.hard_alpa, result.preferred_d_id,
2914  &result);
2915  if (rc == OCS_HAL_RTN_SUCCESS) {
2916  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
2917  /* Undefined failure */
2918  ocs_log_err(ocs, "ocs_sem_p failed\n");
2919  return -ENXIO;
2920  }
2921  if (result.status != 0) {
2922  ocs_log_test(ocs, "setting wwn status 0x%x\n", result.status);
2923  return -1;
2924  }
2925  }
2926 
2927  return rc;
2928 }
2929 
2930 static int
2931 set_tgt_rscn_delay(ocs_t *ocs, char *name, char *value)
2932 {
2933  ocs->tgt_rscn_delay_msec = ocs_strtoul(value, NULL, 0) * 1000;
2934  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2935  return 0;
2936 }
2937 
2938 static int
2939 set_tgt_rscn_period(ocs_t *ocs, char *name, char *value)
2940 {
2941  ocs->tgt_rscn_period_msec = ocs_strtoul(value, NULL, 0) * 1000;
2942  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2943  return 0;
2944 }
2945 
2946 static int
2947 set_inject_drop_cmd(ocs_t *ocs, char *name, char *value)
2948 {
2949  ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_CMD);
2950  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2951  return 0;
2952 }
2953 
2954 static int
2955 set_inject_free_drop_cmd(ocs_t *ocs, char *name, char *value)
2956 {
2957  ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_FREE_DROPPED);
2958  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2959  return 0;
2960 }
2961 
2962 static int
2963 set_inject_drop_data(ocs_t *ocs, char *name, char *value)
2964 {
2965  ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_DATA);
2966  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2967  return 0;
2968 }
2969 
2970 static int
2971 set_inject_drop_resp(ocs_t *ocs, char *name, char *value)
2972 {
2973  ocs->err_injection = (ocs_strtoul(value, NULL, 0) == 0 ? NO_ERR_INJECT : INJECT_DROP_RESP);
2974  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2975  return 0;
2976 }
2977 
2978 static int
2979 set_cmd_err_inject(ocs_t *ocs, char *name, char *value)
2980 {
2981  ocs->cmd_err_inject = ocs_strtoul(value, NULL, 0);
2982  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2983  return 0;
2984 }
2985 
2986 static int
2987 set_cmd_delay_value(ocs_t *ocs, char *name, char *value)
2988 {
2989  ocs->delay_value_msec = ocs_strtoul(value, NULL, 0);
2990  ocs->err_injection = (ocs->delay_value_msec == 0 ? NO_ERR_INJECT : INJECT_DELAY_CMD);
2991  ocs_log_debug(ocs, "mgmt set: %s %s\n", name, value);
2992  return 0;
2993 }
2994 
2995 #if 0
2996 static void
2997 ocs_mgmt_status_hal(ocs_textbuf_t *textbuf, ocs_hal_t *hal)
2998 {
2999  ocs_t *ocs = hal->os;
3000 
3001  ocs_assert(ocs);
3002 
3003  ocs_mgmt_start_section(textbuf, "hal", ocs->ocs_os.instance_index);
3004 
3005 
3006  ocs_mgmt_sli4_queue_status(textbuf, "wq", hal->wq, ARRAY_SIZE(hal->wq));
3007  ocs_mgmt_sli4_queue_status(textbuf, "rq", hal->rq, ARRAY_SIZE(hal->rq));
3008  ocs_mgmt_sli4_queue_status(textbuf, "mq", hal->mq, ARRAY_SIZE(hal->mq));
3009  ocs_mgmt_sli4_queue_status(textbuf, "cq", hal->cq, ARRAY_SIZE(hal->cq));
3010  ocs_mgmt_sli4_queue_status(textbuf, "eq", hal->eq, ARRAY_SIZE(hal->eq));
3011 
3012  ocs_mgmt_end_section(textbuf);
3013  //sli4_link_event_t link;
3014 }
3015 
3016 static void
3017 ocs_mgmt_sli4_queue_status(ocs_textbuf_t *textbuf, const char *name, sli4_queue_t *q, uint32_t q_count)
3018 {
3019  uint32_t i;
3020 
3021  for (i = 0; i < q_count; i ++, q ++) {
3022  ocs_mgmt_start_section(textbuf, name, i);
3023  ocs_mgmt_status_int(textbuf, "index", "%d", q->index);
3024  ocs_mgmt_status_int(textbuf, "size", "%d", q->size);
3025  ocs_mgmt_status_int(textbuf, "length", "%d", q->length);
3026  ocs_mgmt_status_int(textbuf, "n_posted", "%d", q->n_posted);
3027  ocs_mgmt_status_int(textbuf, "id", "%d", q->id);
3028  ocs_mgmt_status_int(textbuf, "type", "%d", q->type);
3029  ocs_mgmt_status_int(textbuf, "limit", "%d", q->limit);
3030  ocs_mgmt_end_section(textbuf);
3031  }
3032 }
3033 #endif
3034 
3035 /**
3036  * @brief parse a WWN from a string into a 64-bit value
3037  *
3038  * Given a pointer to a string, parse the string into a 64-bit
3039  * WWN value. The format of the string must be xx:xx:xx:xx:xx:xx:xx:xx
3040  *
3041  * @param wwn_in pointer to the string to be parsed
3042  * @param wwn_out pointer to uint64_t in which to put the parsed result
3043  *
3044  * @return 0 if successful, non-zero if the WWN is malformed and couldn't be parsed
3045  */
3046 int
3047 parse_wwn(char *wwn_in, uint64_t *wwn_out)
3048 {
3049  uint8_t byte0;
3050  uint8_t byte1;
3051  uint8_t byte2;
3052  uint8_t byte3;
3053  uint8_t byte4;
3054  uint8_t byte5;
3055  uint8_t byte6;
3056  uint8_t byte7;
3057  int rc;
3058 
3059  if (ocs_strchr(wwn_in, ':') == NULL) {
3060  rc = ocs_sscanf(wwn_in, "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
3061  &byte0, &byte1, &byte2, &byte3,
3062  &byte4, &byte5, &byte6, &byte7);
3063  } else {
3064  rc = ocs_sscanf(wwn_in, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
3065  &byte0, &byte1, &byte2, &byte3,
3066  &byte4, &byte5, &byte6, &byte7);
3067  }
3068 
3069  if (rc == 8) {
3070  *wwn_out = ((uint64_t)byte0 << 56) |
3071  ((uint64_t)byte1 << 48) |
3072  ((uint64_t)byte2 << 40) |
3073  ((uint64_t)byte3 << 32) |
3074  ((uint64_t)byte4 << 24) |
3075  ((uint64_t)byte5 << 16) |
3076  ((uint64_t)byte6 << 8) |
3077  ((uint64_t)byte7);
3078  return 0;
3079 
3080  } else {
3081  return -1;
3082  }
3083 }
3084 
3085 
3086 /**
3087  * @page mgmt_api_overview Management APIs
3088  * - @ref mgmt
3089  *
3090  * <div class="overview">
3091  * The management interface provides a mechanism by which a program in user space
3092  * can interact with the running driver. Through the ioctl system call, a user program
3093  * can get a list of the information available, and then read/modify
3094  * individual values. There are three categories of management information:<br/><br/>
3095  *
3096  * - Status - A status is a read-only value. The ocs_mgmt_get_status_list() function
3097  * returns a list of available status properties. The ocs_mgmt_get_status()
3098  * function returns the value of a particular property.
3099  *
3100  * - Configuration - A configuration is a read/write value. The
3101  * ocs_mgmt_get_config_list() function
3102  * returns a list of configuration properties. The ocs_mgmt_get_config() function
3103  * returns the current value of a property. The ocs_mgmt_set_config() function
3104  * changes the value of a property.
3105  *
3106  * - Action - An action allows a user to perform an action in the driver, such as
3107  * updating firmware or bringing a link up/down. The ocs_mgmt_get_action_list()
3108  * function returns a list of available actions. The ocs_mgmt_do_action() function
3109  * invokes a particular action.
3110  *
3111  * </div>
3112  */
3113 
static void get_wwpn(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1306
static void get_current_speed(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1738
ocs_sport_t * ocs_sport_get_instance(ocs_domain_t *domain, uint32_t index)
Return a SLI port object, given an instance index.
Definition: ocs_sport.c:336
static int set_configured_link_state(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2277
#define OCS_CONFIG_LINKCFG_4X10G
linkcfg strings
Definition: ocs_ioctl.h:472
#define BUFFER_SIZE
static void get_node_abort_cnt(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Get accumulated node abort counts.
Definition: ocs_mgmt.c:2757
static void get_sn(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1316
static int set_loglevel(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2193
static void get_inject_drop_data(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1530
static void ocs_mgmt_sfp_cb(void *os, int32_t status, uint32_t bytes_read, uint32_t *data, void *arg)
Definition: ocs_mgmt.c:1143
static void get_cmd_err_inject(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1544
ocs_hal_linkcfg_e linkcfg
Definition: ocs_mgmt.c:1895
ocs_hal_rtn_e ocs_hal_get_itcm_parity_stats(ocs_hal_t *hal, bool clear_stats, ocs_hal_parity_stat_cb_t cb, void *arg)
Definition: ocs_hal.c:6823
static void get_configured_link_state(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1806
ocs_hal_rtn_e ocs_hal_get_sfp(ocs_hal_t *hal, uint16_t page, ocs_hal_sfp_cb_t cb, void *arg)
Function to retrieve the SFP information.
Definition: ocs_hal.c:5759
static int set_inject_free_drop_cmd(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2955
#define FW_WRITE_BUFSIZE
Definition: ocs_mgmt.c:851
#define SFP_PAGE_SIZE
Definition: ocs_mgmt.h:54
ocs_hal_rtn_e ocs_hal_get_port_protocol(ocs_hal_t *hal, uint32_t pci_func, ocs_get_port_protocol_cb_t cb, void *ul_arg)
Get the current port protocol.
Definition: ocs_hal.c:8498
static int ocs_mgmt_port_migration(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:842
ocs_mgmt_action_func action_handler
Definition: ocs_mgmt.h:68
#define SFP_PAGE_A0
Definition: ocs_mgmt.h:55
uint16_t size
Definition: sli4.h:3453
static void get_current_link_state(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1782
#define OCS_DEBUG_ENABLE_MQ_DUMP
Definition: ocs_debug.h:168
static void get_nodedb_mask(ocs_t *, char *, ocs_textbuf_t *)
Get requested nodedb_mask config value.
Definition: ocs_mgmt.c:1963
int ocs_mgmt_get(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Return the value of a management item.
Definition: ocs_mgmt.c:351
void ocs_read_temperature_lancer_cb(int32_t status, uint32_t curr_temp, uint32_t crit_temp_thr, uint32_t warn_temp_thr, uint32_t norm_temp_thr, uint32_t fan_off_thr, uint32_t fan_on_thr, void *arg)
Definition: ocs_mgmt.c:1059
Definition: ocs_mgmt.h:64
int parse_wwn(char *wwn_in, uint64_t *wwn_out)
parse a WWN from a string into a 64-bit value
Definition: ocs_mgmt.c:3047
ocs_mgmt_set_func set_handler
Definition: ocs_mgmt.h:67
static void get_nodes_count(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1229
static int32_t ocs_list_empty(ocs_list_t *list)
Test if a list is empty.
Definition: ocs_list.h:125
ocs_domain_t * ocs_domain_get_instance(ocs_t *ocs, uint32_t index)
Return a pointer to the domain, given the instance index.
Definition: ocs_domain.c:414
static void get_req_wwnn(ocs_t *, char *, ocs_textbuf_t *)
Get requested WWNN config value.
Definition: ocs_mgmt.c:1929
static int set_req_wwnn(ocs_t *, char *, char *)
Set requested WWNN value.
Definition: ocs_mgmt.c:1979
void ocs_mgmt_emit_int(ocs_textbuf_t *textbuf, int mode, const char *name, const char *fmt,...)
Generate a property with an integer value in a management XML document.
static void get_active_xri_count(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1569
#define OCS_CONFIG_LINKCFG_1X40G
Definition: ocs_ioctl.h:473
#define UNSUPPORTED_SFP_ERR_STATUS
uint32_t resp[OCS_DUMP_TYPE4_WKI_TAG_SAT_TEM_RESP_LEN/4]
Definition: ocs_mgmt.c:53
static void get_pci_vendor(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1476
static int set_configured_speed(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2202
static void get_driver_version(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1237
static void get_logmask(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1722
static void get_fw_dump_max_size(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1683
ocs_mgmt_get_func get_handler
Definition: ocs_mgmt.h:66
static void get_pn(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1332
static void ocs_mgmt_get_active_profile_cb(int32_t status, uint32_t active_profile, void *ul_arg)
Definition: ocs_mgmt.c:2536
int ocs_mgmt_set(ocs_t *ocs, char *name, char *value)
Set the value of a mgmt item.
Definition: ocs_mgmt.c:452
static void ocs_mgmt_fw_write_cb(int32_t status, int32_t ext_status, uint32_t actual_write_length, uint32_t change_status, void *arg)
Definition: ocs_mgmt.c:966
ocs_hal_rtn_e ocs_hal_get_profile_list(ocs_hal_t *hal, ocs_get_profile_list_cb_t cb, void *ul_arg)
Get a list of available profiles.
Definition: ocs_hal.c:8955
uint32_t index
Definition: sli4.h:3452
ocs_hal_rtn_e
Definition: ocs_hal.h:159
#define SLI4_MBOX_EXT_STATUS_OBJ_UNSUPPORTED_FIRMWARE
Definition: sli4.h:462
static void get_debug_wq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1708
int ocs_mgmt_exec(ocs_t *ocs, char *action, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
Perform a management action.
Definition: ocs_mgmt.c:538
#define MGMT_MODE_EX
Definition: ocs_mgmt.h:49
#define OCS_MAX_SLI4_ULP
Definition: ocs_ioctl.h:462
#define OCS_CONFIG_LINKCFG_4X8G
Definition: ocs_ioctl.h:475
#define OCS_DUMP_TYPE4_WKI_TAG_SAT_TEM_RESP_LEN
Definition: ocs_ioctl.h:267
static void get_current_topology(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1762
ocs_atomic_t ref_cnt
Definition: ocs_common.h:259
uint32_t segment_count
Definition: ocs_ramdisc.h:107
static void ocs_device_lock(ocs_t *ocs)
Definition: ocs_drv_fc.h:218
const char * name
Definition: ocs_ddump.h:54
static void get_nv_wwpn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Get wwpn.
Definition: ocs_mgmt.c:2682
static int set_port_protocol(ocs_t *, char *, char *)
Set port protocol.
Definition: ocs_mgmt.c:2409
int32_t ocs_device_detach(ocs_t *ocs)
free resources when pci device detach
void ocs_mgmt_start_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
Generate the beginning of an unnumbered section in a management XML document.
static int set_cmd_delay_value(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2987
ramdisc instance structure
Definition: ocs_ramdisc.h:88
static void get_sfp_a0(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1583
ramdisc segment structure
Definition: ocs_ramdisc.h:79
static void get_configured_speed(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1748
void ocs_mgmt_start_section(ocs_textbuf_t *textbuf, const char *name, int index)
Generate the beginning of a numbered section in a management XML document.
int const char const char void ocs_mgmt_emit_boolean(ocs_textbuf_t *textbuf, int access, const char *name, const int value)
Generate a property with a boolean value in a management XML document.
#define OCS_RESET_MODE_PORT_MIGRATION
Definition: ocs_recovery.h:39
static int set_logmask(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2184
static void ocs_domain_unlock(ocs_domain_t *domain)
Definition: ocs_domain.h:70
#define SLI4_ASIC_ID_REG
ASIC_ID - SLI ASIC Type and Revision Register.
Definition: sli4.h:123
ocs_hal_port_protocol_e
Port protocols.
Definition: ocs_hal.h:279
static int ocs_mgmt_force_assert(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:1223
ocs_hal_profile_descriptor_t descriptors[OCS_HAL_MAX_PROFILES]
Definition: ocs_hal.h:301
size_t size
Definition: ocs_ramdisc.h:73
static void get_hw_rev1(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1267
int32_t ocs_mgmt_get_sfp(ocs_t *ocs, uint16_t page, void *buf, uint32_t buf_len)
Definition: ocs_mgmt.c:1165
static int set_debug_wq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2148
void ocs_mgmt_get_list(ocs_t *ocs, ocs_textbuf_t *textbuf)
Get a list of options supported by the driver.
Definition: ocs_mgmt.c:277
static void get_desc(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1243
int32_t ocs_xport_control(ocs_xport_t *xport, ocs_xport_ctrl_e cmd,...)
Perform transport attach function.
Definition: ocs_xport.c:866
static void get_inject_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1516
static int32_t ocs_domain_lock_try(ocs_domain_t *domain)
Definition: ocs_domain.h:56
#define OCS_CONFIG_LINKCFG_UNKNOWN
Definition: ocs_ioctl.h:479
static void ocs_mgmt_get_nvparms_cb(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa, uint32_t preferred_d_id, void *ul_arg)
Definition: ocs_mgmt.c:2656
uint32_t num_descriptors
Definition: ocs_hal.h:300
static void get_req_wwpn(ocs_t *, char *, ocs_textbuf_t *)
Get requested WWPN config value.
Definition: ocs_mgmt.c:1946
void ocs_mgmt_get_all(ocs_t *ocs, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:632
static int ocs_mgmt_read_parity_stats(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
Definition: ocs_mgmt.c:1004
uint32_t ocs_hal_rpi_active_count(ocs_hal_t *hal)
Called to obtain active RPI count.
Definition: ocs_hal.c:9371
#define FW_DUMP_LEVEL_NONE
Definition: ocs_gendump.h:54
static void get_port_protocol(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:2338
uint32_t value
Definition: ocs_xport.h:170
static int set_inject_drop_resp(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2971
static void get_fw_rev(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1249
static void get_nv_wwnn(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Get wwnn.
Definition: ocs_mgmt.c:2720
static int set_tgt_rscn_period(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2939
ramdisc_segment_t ** segments
Definition: ocs_ramdisc.h:106
static void get_wwnn(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1296
void ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
Generate the end of a section in a management XML document.
static void get_pci_device(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1483
uint32_t page_data[32]
Definition: ocs_mgmt.c:1139
static void ocs_device_unlock(ocs_t *ocs)
Definition: ocs_drv_fc.h:223
static void get_phy_port_num(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1358
#define MAX_PROFILE_LENGTH
Definition: ocs_mgmt.c:2546
ocs_hal_linkcfg_e
Link configurations.
Definition: ocs_hal.h:367
static int set_configured_topology(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2238
int32_t ocs_hal_set_nvparms(ocs_hal_t *hal, ocs_set_nvparms_cb_t cb, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa, uint32_t preferred_d_id, void *ul_arg)
Write non-volatile parms.
Definition: ocs_hal.c:9280
uint8_t type
Definition: sli4.h:3460
static void ocs_mgmt_get_port_protocol_cb(int32_t status, ocs_hal_port_protocol_e port_protocol, void *arg)
Definition: ocs_mgmt.c:2325
static int ocs_mgmt_firmware_write(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:863
ocs_hal_rtn_e ocs_hal_get(ocs_hal_t *hal, ocs_hal_property_e prop, uint32_t *value)
Definition: ocs_hal.c:1840
static void ocs_mgmt_read_parity_stats_cb(int32_t status, uint8_t num_ulp, ocs_parity_err_count_t *counter, void *arg)
Definition: ocs_mgmt.c:986
static int32_t ocs_device_lock_try(ocs_t *ocs)
Definition: ocs_drv_fc.h:197
#define OCS_CONFIG_LINKCFG_4X1G
Definition: ocs_ioctl.h:476
void ocs_mgmt_end_section(ocs_textbuf_t *textbuf, const char *name, int index)
Generate the indexed end of a section in a management XML document.
void(* exec_cb)(ocs_domain_t *, void *arg)
Definition: ocs_common.h:260
ocs_hal_profile_list_t * list
Definition: ocs_mgmt.c:2456
#define OCS_DEBUG_ENABLE_CQ_DUMP
Definition: ocs_debug.h:169
static void get_tgt_rscn_period(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1510
static ocs_mgmt_linkcfg_map_t mgmt_linkcfg_map[]
Definition: ocs_mgmt.c:1841
static void get_profile_list(ocs_t *, char *, ocs_textbuf_t *)
Get list of profiles.
Definition: ocs_mgmt.c:2485
int32_t ocs_device_attach(ocs_t *ocs)
Initialize resources when pci devices attach.
static void get_sfp_a2(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1631
A Profile List.
Definition: ocs_hal.h:299
static void get_fw_rev2(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1255
ocs_hal_rtn_e ocs_hal_port_control(ocs_hal_t *hal, ocs_hal_port_e ctrl, uintptr_t value, ocs_hal_port_control_cb_t cb, void *arg)
Control a port (initialize, shutdown, or set link configuration).
Definition: ocs_hal.c:3060
uint16_t length
Definition: sli4.h:3454
uint16_t id
Definition: sli4.h:3456
static void get_hw_rev3(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1287
int32_t ocs_hal_get_nvparms(ocs_hal_t *hal, ocs_get_nvparms_cb_t cb, void *ul_arg)
Read non-volatile parms.
Definition: ocs_hal.c:9178
static void get_chip_type(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1374
void * virt
Definition: ocs_ramdisc.h:71
static void get_lip_count(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1562
static void get_debug_cq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1700
ocs_hal_rtn_e ocs_hal_set_port_protocol(ocs_hal_t *hal, ocs_hal_port_protocol_e new_protocol, uint32_t pci_func, ocs_set_port_protocol_cb_t cb, void *ul_arg)
Set the port protocol.
Definition: ocs_hal.c:8803
static int set_active_profile(ocs_t *, char *, char *)
Set active profile.
Definition: ocs_mgmt.c:2617
uint16_t n_posted
Definition: sli4.h:3455
static void get_fw_dump_present(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1674
static void get_active_profile(ocs_t *, char *, ocs_textbuf_t *)
Get active profile.
Definition: ocs_mgmt.c:2563
#define OCS_CONFIG_LINKCFG_2X16G
Definition: ocs_ioctl.h:474
static ocs_hal_linkcfg_e ocs_hal_linkcfg_from_mgmt(const char *mgmt_str)
Get the HAL linkcfg enum from the mgmt config string.
Definition: ocs_mgmt.c:1858
#define OCS_CTRLMASK_ENABLE_FABRIC_EMULATION
static void ocs_mgmt_get_profile_list_cb(int32_t status, ocs_hal_profile_list_t *list, void *ul_arg)
Definition: ocs_mgmt.c:2460
int32_t ocs_fw_reset(ocs_t *ocs)
Definition: ocs_gendump.c:86
static int set_inject_drop_cmd(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2947
static int set_debug_cq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2130
static void ocs_mgmt_linkcfg_cb(int32_t status, uintptr_t value, void *arg)
Linkcfg callback.
Definition: ocs_mgmt.c:2103
#define MGMT_MODE_RD
Definition: ocs_mgmt.h:47
ocs_hal_rtn_e ocs_hal_get_temperature(ocs_hal_t *hal, ocs_hal_temp_cb_t cb, void *arg)
Function to retrieve the temperature information.
Definition: ocs_hal.c:5814
ocs_hal_rtn_e ocs_hal_set(ocs_hal_t *hal, ocs_hal_property_e prop, uint32_t value)
Definition: ocs_hal.c:2214
static void get_inject_drop_resp(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1537
int32_t ocs_hal_get_active_profile(ocs_hal_t *hal, ocs_get_active_profile_cb_t cb, void *ul_arg)
Get the currently active profile.
Definition: ocs_hal.c:9077
int32_t ocs_hal_set_active_profile(ocs_hal_t *hal, ocs_set_active_profile_cb_t cb, uint32_t profile_id, void *ul_arg)
Set the currently active profile.
Definition: ocs_hal.c:9484
#define OCS_CONFIG_LINKCFG_2X10G
Definition: ocs_ioctl.h:477
static void get_debug_mq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1692
#define SLI4_INTF_REG
SLI_INTF - SLI Interface Definition Register.
Definition: sli4.h:101
static void get_inject_free_drop_cmd(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1523
#define SLI4_PCI_CLASS_REVISION
Definition: sli4.h:85
static void get_asic_id(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1366
int32_t ocs_read_temperature_lancer(ocs_t *ocs, void *buf, uint32_t buf_len)
Definition: ocs_mgmt.c:1083
static int32_t ocs_sport_lock_try(ocs_sport_t *sport)
Definition: ocs_sport.h:60
static void get_businfo(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1556
static void get_tgt_rscn_delay(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1504
int32_t ocs_recovery_reset(ocs_t *ocs, uint32_t reset_mode, uint8_t dump_level, bool trigger_dump)
Initiate FW dump and do reset.
Definition: ocs_recovery.c:361
static void ocs_mgmt_set_active_profile_cb(int32_t status, void *ul_arg)
Definition: ocs_mgmt.c:2593
static int set_cmd_err_inject(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2979
static int set_linkcfg(ocs_t *, char *, char *)
Set linkcfg config value.
Definition: ocs_mgmt.c:2060
static int set_req_wwpn(ocs_t *, char *, char *)
Set requested WWNP value.
Definition: ocs_mgmt.c:2012
uint8_t dif_separate
Definition: ocs_ramdisc.h:93
void ocs_debug_enable(uint32_t mask)
enable debug options
Definition: ocs_debug.c:73
static int set_inject_drop_data(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2963
uint32_t ocs_hal_io_get_count(ocs_hal_t *hal, ocs_hal_io_count_type_e io_count_type)
Called to obtain the count for the specified type.
Definition: ocs_hal.c:9325
uintptr_t phys
Definition: ocs_ramdisc.h:72
ocs_hal_port_protocol_e port_protocol
Definition: ocs_mgmt.c:2320
static void ocs_mgmt_set_port_protocol_cb(int32_t status, void *arg)
Definition: ocs_mgmt.c:2385
static int set_debug_mq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2112
static void get_linkcfg(ocs_t *, char *, ocs_textbuf_t *)
Get linkcfg config value.
Definition: ocs_mgmt.c:1908
static void get_pci_subsystem_device(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1497
static void get_hw_rev2(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1277
static int set_tgt_rscn_delay(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2931
static int ocs_mgmt_function_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:822
ocs_parity_err_count_t counter[OCS_MAX_SLI4_ULP]
Definition: ocs_mgmt.c:982
static const char * ocs_mgmt_from_hal_linkcfg(ocs_hal_linkcfg_e linkcfg)
Get the mgmt string value from the HAL linkcfg enum.
Definition: ocs_mgmt.c:1878
int32_t ocs_get_bus_dev_func(ocs_t *ocs, uint8_t *bus, uint8_t *dev, uint8_t *func)
#define MAX_LINE_SIZE
int ocs_debug_is_enabled(uint32_t mask)
return true if debug bits are enabled
Definition: ocs_debug.c:106
Link configuration callback argument.
Definition: ocs_mgmt.c:1892
static void ocs_mgmt_set_nvparms_cb(int32_t status, void *ul_arg)
Definition: ocs_mgmt.c:2809
#define MGMT_MODE_RW
Definition: ocs_mgmt.h:50
#define MGMT_MODE_WR
Definition: ocs_mgmt.h:48
#define ocs_assert(cond,...)
Definition: ocs_debug.h:176
static int set_nv_wwn(ocs_t *, char *, char *)
Set wwn.
Definition: ocs_mgmt.c:2830
static void get_debug_eq_dump(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1715
static void get_loglevel(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1730
static void get_active_rpi_count(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1575
int access
Definition: ocs_mgmt.h:99
static int32_t ocs_device_lock_try_timeout(ocs_t *ocs, uint32_t timeout_ms, uint8_t retries)
Definition: ocs_drv_fc.h:202
static int set_nodedb_mask(ocs_t *, char *, char *)
Set node debug mask value.
Definition: ocs_mgmt.c:2044
#define FW_DUMP_STATE_NONE
Definition: ocs_gendump.h:59
void * ocs_hal_get_ptr(ocs_hal_t *hal, ocs_hal_property_e prop)
Definition: ocs_hal.c:2175
HAL link config enum to mgmt string value mapping.
Definition: ocs_mgmt.c:1836
ocs_lock_t cb_lock
Definition: ocs_mgmt.c:1135
int32_t ocs_xport_status(ocs_xport_t *xport, ocs_xport_status_e cmd, ocs_xport_stats_t *result)
Return status on a link.
Definition: ocs_xport.c:1073
void ocs_mgmt_emit_string(ocs_textbuf_t *textbuf, int access, const char *name, const char *value)
Generate a property with a string value in a management XML document.
ocs_dma_t data_segment
Definition: ocs_ramdisc.h:80
void ocs_mgmt_domain_exec_cb(ocs_domain_t *domain, void *)
Definition: ocs_domain.c:1603
static void get_logical_link_speed(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1796
#define ocs_list_foreach(list, item)
Iterate a linked list.
Definition: ocs_list.h:428
#define SFP_PAGE_A2
Definition: ocs_mgmt.h:56
static void get_pci_subsystem_vendor(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1490
static void get_sli4_intf_reg(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1350
static void get_ipl(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1261
#define OCS_DEBUG_ENABLE_EQ_DUMP
Definition: ocs_debug.h:171
void * ocs_scsi_get_property_ptr(ocs_t *ocs, ocs_scsi_property_e prop)
Return a property pointer.
Definition: ocs_scsi.c:2871
ocs_hal_linkcfg_e linkcfg
Definition: ocs_mgmt.c:1837
#define OCS_CONFIG_LINKCFG_2X10G_2X8G
Definition: ocs_ioctl.h:478
static void get_cmd_delay_value(ocs_t *ocs, char *name, ocs_textbuf_t *textbuf)
Definition: ocs_mgmt.c:1550
static int set_debug_eq_dump(ocs_t *, char *, char *)
Definition: ocs_mgmt.c:2166
static void ocs_sport_unlock(ocs_sport_t *sport)
Definition: ocs_sport.h:74
ocs_difdma_t dif_segment
Definition: ocs_ramdisc.h:81
static int ocs_mgmt_firmware_reset(ocs_t *ocs, char *, void *buf, uint32_t buf_len, void *, uint32_t)
Definition: ocs_mgmt.c:815
ocs_mgmt_table_entry_t mgmt_table[]
Definition: ocs_mgmt.c:181
void ocs_mgmt_emit_property_name(ocs_textbuf_t *textbuf, int access, const char *name)
Generate a property, with no value, in a management XML document.
uint32_t ocs_scsi_get_property(ocs_t *ocs, ocs_scsi_property_e prop)
Return SCSI API integer valued property.
Definition: ocs_scsi.c:2799
const char * mgmt_str
Definition: ocs_mgmt.c:1838
void ocs_debug_disable(uint32_t mask)
disable debug options
Definition: ocs_debug.c:89
ocs_hal_rtn_e ocs_hal_firmware_write(ocs_hal_t *hal, ocs_dma_t *dma, uint32_t size, uint32_t offset, int last, ocs_hal_fw_cb_t cb, void *arg)
Write a portion of a firmware image to the device.
Definition: ocs_hal.c:5569
#define OCS_DEBUG_ENABLE_WQ_DUMP
Definition: ocs_debug.h:170
static void get_configured_topology(ocs_t *, char *, ocs_textbuf_t *)
Definition: ocs_mgmt.c:1772