Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
common/ocs_fc/ocs_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2018, 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 #include "ocs.h"
34 #include "ocs_driver.h"
35 #include "ocs_vpd.h"
36 #include "ocs_mgmt.h"
37 #include "ocs_gendump.h"
38 #include "ocs_ras.h"
39 #include "ocs_recovery.h"
40 #include "ocs_pm.h"
41 #include "ocs_els.h"
42 
43 #include "ocs_params.h"
44 
45 static void ocs_device_interrupt_handler(ocs_t *ocs, uint32_t vector);
46 static void ocs_driver_print_module_params(void);
47 
48 void ocs_mgmt_driver_list(ocs_textbuf_t *textbuf, void *driver);
49 void ocs_mgmt_driver_get_all(ocs_textbuf_t *textbuf, void *driver);
50 int ocs_mgmt_driver_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *driver);
51 int ocs_mgmt_driver_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
52  void *arg_out, uint32_t arg_out_length, void *driver);
53 int ocs_run_link_loopback(ocs_t *ocs, void *tx_buf, uint32_t tx_buflen, void *rx_buf, uint32_t rx_buflen);
54 int ocs_run_pci_loopback(ocs_t *ocs, void *tx_buf, uint32_t tx_buflen, void *rx_buf, uint32_t rx_buflen);
55 int ocs_set_loopback_mode(ocs_t *ocs, uint32_t arg_in);
56 int ocs_set_fc_trunk_mode(ocs_t *ocs, uint32_t trunk_mode);
57 int ocs_get_fc_trunk_info(ocs_t *ocs, uint32_t *trunk_config);
58 int ocs_ras_collect_diag_logs(ocs_t *ocs, void *user_tx_buf, uint32_t user_tx_buflen,
59  void *user_rx_buf, uint32_t rx_buf_len);
60 
63  .get_handler = ocs_mgmt_driver_get,
64  .get_all_handler = ocs_mgmt_driver_get_all,
65  .exec_handler = ocs_mgmt_driver_exec,
66 };
67 
68 #define FW_WRITE_BUFSIZE 64*1024
69 typedef struct ocs_fw_write_result {
70  ocs_sem_t semaphore;
71  int32_t status;
72  int32_t ext_status;
73  uint32_t actual_xfer;
74  uint32_t change_status;
76 
77 #define INTERNAL_LOOPBACK 0x1
78 #define EXTERNAL_LOOPBACK 0x2
79 #define PCI_LOOPBACK 0x3
80 #define LOOPBACK_FRAME_TIMEOUT_SEC 5
81 
82 /* global param for ocs_app_watchdog_thread_t */
84 
85 
86 
87 static void
89 {
90  char prop_buf[32];
91  uint32_t fw_diag_log_size = 0;
92  uint32_t fw_diag_log_level = 1;
93 
94  hal_global.queue_topology_string = queue_topology;
95 
96  if (ocs_get_property("fw_diag_log_size", prop_buf, sizeof(prop_buf)) == 0) {
97  char *p;
98  fw_diag_log_size = ocs_strtoul(prop_buf, &p, 0);
99  switch(*p) {
100  case 'm': case 'M':
101  fw_diag_log_size *= 1024;
102  /* fallthrough */
103  case 'k': case 'K':
104  fw_diag_log_size *= 1024;
105  break;
106  default:
107  // invalid parameter, disable the feature
108  fw_diag_log_size *= 0;
109  }
110  if (fw_diag_log_size) {
111  if (fw_diag_log_size > OCS_RAS_LOGICAL_BUFFER_SIZE_MAX)
112  fw_diag_log_size = OCS_RAS_LOGICAL_BUFFER_SIZE_MAX;
113  if (fw_diag_log_size < OCS_RAS_LOGICAL_BUFFER_SIZE_MIN)
114  fw_diag_log_size = OCS_RAS_LOGICAL_BUFFER_SIZE_MIN;
115  // verify and adjust logical buffer size to multiple of 128KB
116  fw_diag_log_size = (fw_diag_log_size / OCS_RAS_LOGICAL_BUFFER_SIZE_MIN) *
118  }
119  }
120  hal_global.fw_diag_log_size = fw_diag_log_size;
121 
122  if (ocs_get_property("fw_diag_log_level", prop_buf, sizeof(prop_buf)) == 0) {
123  fw_diag_log_level = ocs_strtoul(prop_buf, 0, 0);
124  if (fw_diag_log_level > OCS_RAS_FW_LOG_LEVEL_MAX)
125  fw_diag_log_level = OCS_RAS_FW_LOG_LEVEL_MAX;
126  }
127  hal_global.fw_diag_log_level = fw_diag_log_level;
128 }
129 
130 
131 /**
132  * @brief Perform driver wide initialization
133  *
134  * This function is called prior to enumerating PCI devices, with subsequent calls
135  * to ocs_device_attach. For OCS, this function invokes the back end functions
136  * ocs_scsi_tgt_driver_init(), and ocs_scsi_ini_driver_init()
137  *
138  * @return returns 0 for success, a negative error code value for failure.
139  */
140 int32_t
142 {
143  int32_t rc;
144 
146  ocs_thread_init();
147 
148  /* Get the CPU mask */
149  g_app_watchdog_cpu_mask = heartbeat_cpu_mask;
150 
151  /* driver-wide init for target-server */
152  if (target) {
154  if (rc) {
155  ocs_log_err(NULL, "ocs_scsi_tgt_init failed rc=%d\n", rc);
156  return -ENOMEM;
157  }
158  }
159 
160  /*
161  * Attach ML FC transport template for both I+T modes.
162  * For T only mode, this is required for Scsi_Host sysfs interface.
163  */
164  if (initiator || target) {
165  rc = ocs_scsi_ini_driver_init(initiator);
166  if (rc) {
167  ocs_log_err(NULL, "ocs_scsi_ini_init failed rc=%d\n", rc);
168  return -ENOMEM;
169  }
170  }
171 
172  /* Print module Parameters */
174 
175  return 0;
176 }
177 
178 /**
179  * @brief Perform device initialization complete
180  *
181  * This function is called after all PCI device/functions have been enumerated.
182  *
183  * @return returns 0 for success, a negative error code value for failure.
184  */
185 int32_t
187 {
188  ocs_t *ocs;
189  int32_t rc, index = 0;
190 
191  /* Setup FW error recovery */
192  if (enable_auto_recovery) {
194  if (rc < 0) {
195  ocs_log_err(NULL, "Failed to setup FW error recovery\n");
196  return rc;
197  }
198  }
199 
200  if (holdoff_link_online == 1) {
201  while ((ocs = ocs_get_instance(index++)) != NULL) {
203  }
204  }
205 
206  return 0;
207 }
208 
209 /**
210  * @brief Perform driver wide shutdown actions
211  *
212  * This function is called prior to detatching devices during a driver
213  * unload.
214  *
215  * @return none
216  */
217 void
219 {
220  if (enable_auto_recovery) {
222  }
223 }
224 
225 /**
226  * @brief Perform driver wide shutdown complete actions
227  *
228  * This function is called shutdown for all devices has completed
229  *
230  * @return none
231  */
232 void
234 {
235  if (initiator || target) {
236  ocs_scsi_ini_driver_exit(initiator);
237  }
238 
239  if (target) {
241  }
242 }
243 
244 /*
245  * @brief allocate ocs device
246  *
247  * @param nid Numa node ID
248  *
249  * @return pointer to OCS structure
250  */
251 
252 void *ocs_device_alloc(int32_t nid)
253 {
254  ocs_t *ocs = NULL;
255  uint32_t i;
256 
257  /* Allocate memory using nid only if it has valid NUMA node avalible*/
258  if (nid < 0) {
259  ocs = ocs_malloc(NULL, sizeof(*ocs), OCS_M_NOWAIT | OCS_M_ZERO);
260  } else {
261  ocs = ocs_malloc_nid(nid, sizeof(*ocs), OCS_M_NOWAIT | OCS_M_ZERO);
262  }
263  if (ocs != NULL) {
264  for (i = 0; i < ARRAY_SIZE(ocs_devices); i ++) {
265  if (ocs_devices[i] == NULL) {
266  ocs->instance_index = i;
267  ocs_devices[i] = ocs;
268  break;
269  }
270  }
271 
272  if (i == ARRAY_SIZE(ocs_devices)) {
273  ocs_log_err(NULL, "failed\n");
274  ocs_free(ocs, ocs, sizeof(*ocs));
275  ocs = NULL;
276  } else {
277  /* If enabled, initailize a RAM logging buffer */
278  if (logdest & 2) {
279  ocs->ramlog = ocs_ramlog_init(ocs, ramlog_size/OCS_RAMLOG_DEFAULT_BUFFERS,
281  /* If NULL was returned, then we'll simply skip using the ramlog but */
282  /* set logdest to 1 to ensure that we at least get default logging. */
283  if (ocs->ramlog == NULL) {
284  logdest = 1;
285  }
286  }
287 
288  /* initialize a saved ddump */
289  if (ddump_saved_size) {
290  if (ocs_textbuf_alloc(ocs, &ocs->ddump_saved, ddump_saved_size)) {
291  ocs_log_err(ocs, "failed to allocate memory for saved ddump\n");
292  }
293  }
294 
295 #if defined(ENABLE_LOCK_DEBUG)
296  ocs_list_init(&ocs->ocs_os.locklist, ocs_lock_t, link);
297  ocs_lock_init(NULL, &ocs->ocs_os.locklist_lock, "locklist_lock[%d]", ocs->instance_index);
298 #endif
299  ocs_list_init(&ocs->domain_list, ocs_domain_t, link);
300  ocs->ocs_os.interrupt_cb = ocs_device_interrupt_handler;
302  ocs->drv_ocs.attached = FALSE;
303  ocs->ocs_os.hw_cmpl_context = hw_cmpl_context;
304  ocs->mgmt_functions = &driver_mgmt_functions;
305 #ifdef OCS_DEBUG_MEMORY
306  ocs_memory_tracker_init(ocs, &ocs->ocs_os.tracker);
307 #endif
308  }
309  }
310  return ocs;
311 }
312 
313 /**
314  * @brief free ocs device
315  *
316  * @param ocs pointer to ocs structure
317  *
318  * @return none
319  */
320 
321 void ocs_device_free(ocs_t *ocs)
322 {
323  if (ocs != NULL) {
324  ocs_textbuf_free(ocs, &ocs->ddump_saved);
325  ocs_ramlog_free(ocs, ocs->ramlog);
326  ocs_devices[ocs->instance_index] = NULL;
328 #if defined(ENABLE_LOCK_DEBUG)
329  {
330  ocs_os_t *os = &ocs->ocs_os;
331  ocs_lock_t *l;
332  uint32_t count = 0;
333  ocs_list_foreach(&os->locklist, l) {
334  ocs_log_debug(os, "%s not freed\n", l->name);
335  count++;
336  }
337  if (count == 0) {
338  ocs_log_debug(ocs, "all lock objects freed\n");
339  }
340  }
341 #endif
342 #ifdef OCS_DEBUG_MEMORY
343  ocs_memory_allocated_print(&ocs->ocs_os.tracker);
344  ocs_memory_tracker_teardown(&ocs->ocs_os.tracker);
345 #endif
346  ocs_free(NULL, ocs, sizeof(*ocs));
347  }
348 }
349 
350 /**
351  * @brief return the number of interrupts required per HBA
352  *
353  * @param ocs pointer to ocs structure
354  *
355  * @return the number of interrupts or a negative value on error.
356  */
357 int32_t
359 {
360  if (ocs_hal_setup(&ocs->hal, ocs, SLI4_PORT_TYPE_FC) !=
362  return -1;
363  }
364  return ocs_hal_qtop_eq_count(&ocs->hal);
365 }
366 
367 /**
368  * @brief Initialize resources when pci devices attach
369  *
370  * @param ocs pointer to ocs structure
371  *
372  * @return 0 for success, a negative error code value for failure.
373  */
374 
375 int32_t
376 ocs_device_attach(ocs_t *ocs)
377 {
378  uint32_t rc = 0;
379 
380  if (ocs->drv_ocs.attached) {
381  ocs_log_warn(ocs, "Device is already attached\n");
382  rc = -1;
383  } else {
384  ocs_snprintf(ocs->display_name, sizeof(ocs->display_name), "[%s%d] ", "fc", ocs->instance_index);
385 
386  ocs->logmask = logmask;
387  ocs->enable_ini = initiator;
388  ocs->enable_tgt = target;
389  ocs->ctrlmask = ctrlmask;
390  ocs->topology = topology;
391  ocs->speed = speed;
392  ocs->ethernet_license = ethernet_license;
393  ocs->num_scsi_ios = num_scsi_ios;
394  ocs->enable_hlm = enable_hlm;
395  ocs->enable_dpp = enable_dpp;
396  ocs->hlm_group_size = hlm_group_size;
397  ocs->max_remote_nodes = max_remote_nodes;
398  ocs->hal_war_version = hal_war_version;
399  ocs->watchdog_timeout = watchdog_timeout;
400  ocs->sliport_healthcheck = sliport_healthcheck;
401  ocs->disable_fec = disable_fec;
402  ocs->enable_fw_ag_rsp = enable_fw_ag_rsp;
403  ocs->sliport_pause_errors = sliport_pause_errors;
404  ocs->enable_bbcr = enable_bbcr;
405  ocs->enable_auto_recovery = enable_auto_recovery;
406 #if defined(OCS_INCLUDE_RAMD)
407  ocs->esoc = esoc;
408  ocs->num_vports = num_vports;
409 #endif
410  ocs->max_isr_time_msec = OCS_OS_MAX_ISR_TIME_MSEC;
411  ocs->explicit_buffer_list = explicit_buffer_list;
412  ocs->model = ocs_pci_model(ocs->pci_vendor, ocs->pci_device);
413  ocs->fw_version = (const char*) ocs_hal_get_ptr(&ocs->hal, OCS_HAL_FW_REV);
414  ocs->driver_version = DRV_VERSION;
415 
416  ocs->external_loopback = external_loopback;
417  ocs->target_io_timer_sec = target_io_timer;
418  ocs->tgt_wqe_timer = target_wqe_timer;
419 
420  ocs->tgt_rscn_delay_msec = 0;
421  ocs->tgt_rscn_period_msec = 0;
422 
423  ocs->hal_bounce = hal_bounce;
424  ocs->rq_threads = rq_threads;
425  ocs->rq_selection_policy = rq_selection_policy;
426  ocs->cq_process_limit = cq_process_limit;
427  ocs->rr_quanta = rr_quanta;
428  ocs->filter_def = filter_def;
429  ocs->ocs_req_fw_upgrade = ocs_req_fw_upgrade;
430  ocs->cfg_suppress_rsp = cfg_suppress_rsp;
431 
432  if (ocs->max_remote_nodes > MAX_REMOTE_NODES_ALLOWED) {
433  ocs_log_err(ocs, "failed to allocate %d number of remote nodes, max remote nodes allowed is 8192\n ",ocs->max_remote_nodes);
434  return -1;
435  }
436 
437  if (fw_dump_type != FW_DUMP_TYPE_DUMPTOHOST &&
438  fw_dump_type != FW_DUMP_TYPE_FLASH) {
439  ocs_log_info(ocs, "Module param FW dump type is invalid. "
440  "Using FW dump type as default\n");
441  fw_dump_type = MODPARAM_DEF_FW_DUMP_TYPE;
442  }
443  ocs_fw_dump_init(ocs, fw_dump_type);
444 
445  ocs_lock_init(ocs, &ocs->domain_list_empty_cb_lock,
446  "domain_list_empty_cb_lock[%d]", ocs_instance(ocs));
447 
448  if (target_wqe_timer > MAX_TARGET_WQE_TIMER) {
449  ocs_log_err(ocs, "Invalid target wqe timer value %d\n", target_wqe_timer);
450  return -1;
451  }
452  /* Allocate transport object and bring online */
453  ocs->xport = ocs_xport_alloc(ocs);
454  if (ocs->xport == NULL) {
455  ocs_log_err(ocs, "failed to allocate transport object\n");
456  rc = -1;
457  } else if (ocs_xport_attach(ocs->xport) != 0) {
458  ocs_log_err(ocs, "failed to attach transport object\n");
459  rc = -1;
460  } else if (ocs_xport_initialize(ocs->xport) != 0) {
461  ocs_log_err(ocs, "failed to initialize transport object\n");
462  rc = -1;
463  } else if (ocs_start_event_processing(&ocs->ocs_os)) {
464  ocs_log_err(ocs, "failed to start event processing\n");
465  rc = -1;
466  } else {
467  /* For some drivers, such as SCST and LIO, the link is not brought up if
468  * the driver is in target mode, because the link comes up after the target
469  * is enabled.
470  * If the driver is in initiator-only mode, then then bring the link up now.
471  */
472 
473  if ((holdoff_link_online == 2) && ((!ocs->enable_tgt) && (ocs->enable_ini))) {
474  holdoff_link_online = 0;
475  ocs_log_debug(ocs, "holdoff_link_online param changed to %d\n",
476  holdoff_link_online);
477  }
478 
479  if (holdoff_link_online == 0) {
480  if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE) != 0) {
481  /*
482  * Only log a message. Don't return the error,
483  * so that the driver will still attach to this port.
484  */
485  ocs_log_err(ocs, "failed to bring port online\n");
486  }
487  }
488 
489  ocs->holdoff_link_online = holdoff_link_online;
490 
491  /*
492  * Setup stats timer only if scsi host template is
493  * registered successfully
494  */
495  if (ocs_scsi_host_ml_registered(ocs)) {
496  /* Get FC link and host statistics periodically */
497  ocs_lock(&ocs->xport->fc_stats_lock);
498  ocs->xport->fc_stats_timer_shutdown = false;
499  ocs_unlock(&ocs->xport->fc_stats_lock);
501  }
502  }
503 
504  ocs->desc = ocs->hal.sli.config.modeldesc;
505  ocs_log_info(ocs, "adapter model description: %s\n", ocs->hal.sli.config.modeldesc);
506 
507  if (rc == 0) {
508  ocs->drv_ocs.attached = TRUE;
509 
510  if (ocs->ocs_req_fw_upgrade) {
511  ocs_log_debug(ocs, "firmware update is in progress\n");
513  }
514 
515  } else {
516  ocs_teardown_msix((ocs_os_t *)ocs);
517  if (ocs->xport != NULL) {
518  ocs_xport_free(ocs->xport);
519  ocs->xport = NULL;
520  }
521  }
522  }
523 
524  return rc;
525 }
526 
527 /**
528  * @brief interrupt handler
529  *
530  * Interrupt handler
531  *
532  * @param ocs pointer to ocs structure
533  * @param vector Zero-based interrupt vector number.
534  *
535  * @return none
536  */
537 
538 static void
539 ocs_device_interrupt_handler(ocs_t *ocs, uint32_t vector)
540 {
541  ocs_hal_process(&ocs->hal, vector, ocs->max_isr_time_msec);
542 }
543 
544 /**
545  * @brief free resources when pci device detach
546  *
547  * @param ocs pointer to ocs structure
548  *
549  * @return 0 for success, a negative error code value for failure.
550  */
551 
552 int32_t
553 ocs_device_detach(ocs_t *ocs)
554 {
555  int32_t rc = 0;
556 
557  if (ocs != NULL) {
558  if (!ocs->drv_ocs.attached) {
559  ocs_log_warn(ocs, "Device is not attached\n");
560  return -1;
561  }
562 
563  rc = ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN);
564  if (rc) {
565  ocs_log_err(ocs, "Transport Shutdown timed out\n");
566  }
567 
568  if (ocs_hal_clear_dump_location(&ocs->hal)) {
569  ocs_log_err(ocs, "failed to clear FW dump location\n");
570  }
571 
572  ocs_stop_event_processing(&ocs->ocs_os);
573 
574  if (ocs_xport_detach(ocs->xport) != 0) {
575  ocs_log_err(ocs, "Transport detach failed\n");
576  }
577 
578  ocs_xport_free(ocs->xport);
579  ocs->xport = NULL;
581  ocs_lock_free(&ocs->domain_list_empty_cb_lock);
582  ocs->drv_ocs.attached = FALSE;
583  }
584 
585  return 0;
586 }
587 
588 /**
589  * @brief get driver wide property value
590  *
591  * Return valued driver wide property. All property values using this interface
592  * are returned as null terminated text.
593  *
594  * @param prop_name property name
595  * @param buffer pointer to buffer
596  * @param buffer_len length of buffer in bytes
597  *
598  * @return returns 0 for success, a negative error code value for failure.
599  */
600 
601 int32_t
602 ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
603 {
604  if (FALSE)
605  ;
606  else if (strcmp(prop_name, "initiator") == 0)
607  ocs_snprintf(buffer, buffer_len, "%d", initiator);
608  else if (strcmp(prop_name, "target") == 0)
609  ocs_snprintf(buffer, buffer_len, "%d", target);
610  else if (strcmp(prop_name, "wwn_bump") == 0)
611  ocs_snprintf(buffer, buffer_len, "%s", wwn_bump);
612  else if (strcmp(prop_name, "dif_separate") == 0)
613  ocs_snprintf(buffer, buffer_len, "%d", dif_separate);
614  else if (strcmp(prop_name, "p_type") == 0)
615  ocs_snprintf(buffer, buffer_len, "%d", p_type);
616  else if (strcmp(prop_name, "fw_diag_log_level") == 0)
617  ocs_snprintf(buffer, buffer_len, "%d", fw_diag_log_level);
618  else if (strcmp(prop_name, "fw_diag_log_size") == 0)
619  ocs_snprintf(buffer, buffer_len, "%s", fw_diag_log_size);
620  else if (strcmp(prop_name, "tow_feature") == 0)
621  ocs_snprintf(buffer, buffer_len, "%d", tow_feature);
622  else if (strcmp(prop_name, "tow_io_size") == 0)
623  ocs_snprintf(buffer, buffer_len, "%d", tow_io_size);
624  else if (strcmp(prop_name, "tow_xri_cnt") == 0)
625  ocs_snprintf(buffer, buffer_len, "%d", tow_xri_cnt);
626 #if defined(OCS_INCLUDE_SCST)
627  else if (strcmp(prop_name, "scst_sg_table_size") == 0)
628  ocs_snprintf(buffer, buffer_len, "%d", scst_sg_table_size);
629 #endif
630 #if defined(OCS_INCLUDE_RAMD)
631  else if (strcmp(prop_name, "global_ramdisc") == 0)
632  ocs_snprintf(buffer, buffer_len, "%d", global_ramdisc);
633  else if (strcmp(prop_name, "ramdisc_size") == 0)
634  ocs_strncpy(buffer, ramdisc_size, buffer_len);
635  else if (strcmp(prop_name, "ramdisc_blocksize") == 0)
636  ocs_snprintf(buffer, buffer_len, "%d", ramdisc_blocksize);
637  else if (strcmp(prop_name, "num_luns") == 0)
638  ocs_snprintf(buffer, buffer_len, "%d", num_luns);
639  else if (strcmp(prop_name, "stub_res6_rel6") == 0)
640  ocs_snprintf(buffer, buffer_len, "%d", stub_res6_rel6);
641  else if (strcmp(prop_name, "ramd_threading") == 0)
642  ocs_snprintf(buffer, buffer_len, "%d", ramd_threading);
643  else if (strcmp(prop_name, "thread_cmds") == 0)
644  ocs_snprintf(buffer, buffer_len, "%d", thread_cmds);
645  else if (strcmp(prop_name, "external_dif") == 0)
646  ocs_strncpy(buffer, external_dif, buffer_len);
647  else if (strcmp(prop_name, "esoc") == 0)
648  ocs_snprintf(buffer, buffer_len, "%d", esoc);
649 #if defined(OCS_DISC_SPIN_DELAY)
650  else if (strcmp(prop_name, "disk_spin_delay") == 0)
651  ocs_snprintf(buffer, disk_spin_delay, "%d", disk_spin_delay);
652 #endif
653 #endif
654  else {
655  ocs_log_debug(NULL, "Error: unknown property %s\n", prop_name);
656  ocs_snprintf(buffer, buffer_len, "%s", "");
657  return -1;
658  }
659  return 0;
660 }
661 
662 static void
663 ocs_fw_write_cb(int32_t status, int32_t ext_status, uint32_t actual_write_length, uint32_t change_status, void *arg)
664 {
665  ocs_fw_write_result_t *result = arg;
666 
667  result->status = status;
668  result->actual_xfer = actual_write_length;
669  result->change_status = change_status;
670  result->ext_status = ext_status;
671 
672  ocs_sem_v(&(result->semaphore));
673 }
674 
675 int
676 ocs_firmware_write(ocs_t *ocs, const u8 *buf, size_t buf_len, uint8_t *change_status)
677 {
678  int rc = 0;
679  uint32_t bytes_left;
680  uint32_t xfer_size;
681  uint32_t offset;
682  ocs_dma_t dma;
683  int last = 0;
684  ocs_fw_write_result_t result;
685 
686  ocs_sem_init(&(result.semaphore), 0, "fw_write");
687 
688  bytes_left = buf_len;
689  offset = 0;
690 
691  if (ocs_dma_alloc(ocs, &dma, FW_WRITE_BUFSIZE, 4096)) {
692  ocs_log_err(ocs, "ocs_firmware_write: malloc failed\n");
693  return -ENOMEM;
694  }
695 
696  while (bytes_left > 0) {
697 
698  if (bytes_left > FW_WRITE_BUFSIZE) {
699  xfer_size = FW_WRITE_BUFSIZE;
700  } else {
701  xfer_size = bytes_left;
702  }
703 
704  ocs_memcpy(dma.virt, buf + offset, xfer_size);
705 
706  if (bytes_left == xfer_size) {
707  last = 1;
708  }
709 
710  ocs_hal_firmware_write(&ocs->hal, &dma, xfer_size, offset, last, ocs_fw_write_cb, &result);
711 
712  if (ocs_sem_p(&(result.semaphore), OCS_SEM_FOREVER) != 0) {
713  rc = -ENXIO;
714  break;
715  }
716 
717  if (result.actual_xfer == 0 || result.status != 0) {
719  ocs_log_err(ocs, "Firmware does not meet minimum version requirement for this IPL\n");
720  rc = -EACCES;
721  } else {
722  rc = -EFAULT;
723  }
724  break;
725  }
726 
727  if (last) {
728  *change_status = result.change_status;
729  }
730 
731  bytes_left -= result.actual_xfer;
732  offset += result.actual_xfer;
733  }
734 
735  ocs_dma_free(ocs, &dma);
736  return rc;
737 }
738 
739 int
741 {
742  int rc = 0;
743  uint8_t file_name[256], fw_change_status;
744  const struct firmware *fw;
745  struct ocs_hal_grp_hdr *fw_image;
746 
747  ocs_snprintf(file_name, 256, "%s.grp", ocs->model);
748  rc = request_firmware(&fw, file_name, &ocs->ocs_os.pdev->dev);
749  if (rc) {
750  ocs_log_err(ocs, "Firmware file(%s) not found.\n", file_name);
751  return rc;
752  }
753  fw_image = (struct ocs_hal_grp_hdr *)fw->data;
754 
755  /* Check if firmware provided is compatible with this particular
756  * Adapter of not*/
757  if ((ocs_be32toh(fw_image->magic_number) != OCS_HAL_OBJECT_G5) &&
758  (ocs_be32toh(fw_image->magic_number) != OCS_HAL_OBJECT_G6)) {
759  ocs_log_warn(ocs,
760  "Invalid FW image found Magic: 0x%x Size: %ld \n",
761  ocs_be32toh(fw_image->magic_number), fw->size);
762  rc = -1;
763  goto exit;
764 
765  }
766 
767  if (!strncmp(ocs->fw_version, fw_image->revision, strnlen(fw_image->revision, 16))) {
768  ocs_log_debug(ocs, "No update req. Firmware is already up to date. \n");
769  rc = 0;
770  goto exit;
771  }
772  rc = ocs_firmware_write(ocs, fw->data, fw->size, &fw_change_status);
773  if (rc) {
774  ocs_log_err(ocs, "Firmware update failed. Return code = %d\n", rc);
775  } else {
776  ocs_log_info(ocs, "Firmware updated successfully\n");
777  switch (fw_change_status) {
778  case 0x00:
779  ocs_log_debug(ocs, "No reset needed, new firmware is active.\n");
780  break;
781  case 0x01:
782  ocs_log_warn(ocs,
783  "A physical device reset (host reboot) is needed to"
784  "activate the new firmware\n");
785  break;
786  case 0x02:
787  case 0x03:
788  ocs_log_debug(ocs,
789  "firmware is resetting to activate the new firmware\n");
790  ocs_fw_reset(ocs);
791  break;
792  default:
793  ocs_log_debug(ocs,
794  "Unexected value change_status: %d\n",
795  fw_change_status);
796  break;
797  }
798 
799  }
800 
801 exit:
802  release_firmware(fw);
803 
804  return rc;
805 
806 }
807 
808 
809 
810 
811 
812 /**
813  * @brief return OCS instance display name
814  *
815  * returns const char string of OCS instance display name
816  *
817  * @param os pointer to OS (ocs_t) object
818  *
819  * @return return display name
820  */
821 
822 const char *ocs_display_name(void *os)
823 {
824  ocs_t *ocs = os;
825  ocs_assert(ocs, "[?]");
826  return ocs->display_name;
827 }
828 
829 void ocs_mgmt_driver_list(ocs_textbuf_t *textbuf, void *object)
830 {
831 
832  ocs_mgmt_start_unnumbered_section(textbuf, "driver");
833 
834  /* Add my values to textbuf */
835  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "initiator");
836  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "target");
837  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "logmask");
838  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ctrlmask");
839  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "logdest");
840  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ramlog_size");
841  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hal_war_version");
842  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_scsi_ios");
843  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "pm_state");
844  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ddump_saved_size");
845  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "dif_separate");
846 #if defined(OCS_INCLUDE_FC)
847  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "wwn_bump");
848  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "topology");
849  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "speed");
850  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "holdoff_link_online");
851  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_hlm");
852  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_dpp");
853  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hlm_group_size");
854  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "explicit_buffer_list");
855  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hw_cmpl_context");
856  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "external_loopback");
857  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "target_io_timer");
858  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "target_wqe_timer");
859  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "auto_xfer_rdy_size");
860 #endif
861 #if defined(OCS_INCLUDE_RAMD)
862  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_luns");
863  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "global_ramd");
864  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ramdisc_blocksize");
865  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ramdisc_size");
866  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "p_type");
867  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "stub_res6_rel6");
868 #endif
869  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "gendump");
870  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "fdb_gendump");
871  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "dump_to_host");
872  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "fdb_dump_to_host");
873  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "clear_ramlog");
874  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_sleep");
875  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_prepare");
876  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_hibernate");
877  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_resume");
878  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "gen_saved_ddump");
879 
880  ocs_mgmt_end_unnumbered_section(textbuf, "driver");
881 
882 }
883 
884 int ocs_mgmt_driver_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
885 {
886  char qualifier[80];
887  int retval = -1;
888 
889  ocs_mgmt_start_unnumbered_section(textbuf, "driver");
890 
891  snprintf(qualifier, sizeof(qualifier), "%s/driver", parent);
892 
893  /* If it doesn't start with my qualifier I don't know what to do with it */
894  if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
895  char *unqualified_name = name + strlen(qualifier) +1;
896 
897  /* See if it's a value I can supply */
898  if (FALSE) {
899  ;
900  } else if (ocs_strcmp(unqualified_name, "initiator") == 0) {
901  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "initiator", initiator);
902  retval = 0;
903  } else if (ocs_strcmp(unqualified_name, "target") == 0) {
904  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "target", target);
905  retval = 0;
906  } else if (ocs_strcmp(unqualified_name, "logmask") == 0) {
907  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "logmask", "0x%x", logmask);
908  retval = 0;
909  } else if (ocs_strcmp(unqualified_name, "ctrlmask") == 0) {
910  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ctrlmask", "0x%x", ctrlmask);
911  retval = 0;
912  } else if (ocs_strcmp(unqualified_name, "logdest") == 0) {
913  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "logdest", "%d", logdest);
914  retval = 0;
915  } else if (ocs_strcmp(unqualified_name, "ramlog_size") == 0) {
916  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramlog_size", "%d", ramlog_size);
917  retval = 0;
918  } else if (ocs_strcmp(unqualified_name, "hal_war_version") == 0) {
919  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "hal_war_version", hal_war_version);
920  retval = 0;
921  } else if (ocs_strcmp(unqualified_name, "num_scsi_ios") == 0) {
922  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_scsi_ios", "%d", num_scsi_ios);
923  retval = 0;
924  } else if (ocs_strcmp(unqualified_name, "pm_state") == 0) {
925  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pm_state", ocs_pm_get_state_string(textbuf->ocs));
926  retval = 0;
927  } else if (ocs_strcmp(unqualified_name, "ddump_saved_size") == 0) {
928  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ddump_saved_size", "%d", ddump_saved_size);
929  retval = 0;
930  } else if (ocs_strcmp(unqualified_name, "dif_separate") == 0) {
931  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "dif_separate", dif_separate);
932  retval = 0;
933 #if defined(OCS_INCLUDE_FC)
934  } else if (ocs_strcmp(unqualified_name, "wwn_bump") == 0) {
935  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "wwn_bump", wwn_bump);
936  retval = 0;
937  } else if (ocs_strcmp(unqualified_name, "topology") == 0) {
938  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "topology", "%d", topology);
939  retval = 0;
940  } else if (ocs_strcmp(unqualified_name, "speed") == 0) {
941  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "speed", "%d", speed);
942  retval = 0;
943  } else if (ocs_strcmp(unqualified_name, "holdoff_link_online") == 0) {
944  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "holdoff_link_online", holdoff_link_online);
945  retval = 0;
946  } else if (ocs_strcmp(unqualified_name, "enable_hlm") == 0) {
947  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_hlm", enable_hlm);
948  retval = 0;
949  } else if (ocs_strcmp(unqualified_name, "enable_dpp") == 0) {
950  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_dpp", enable_dpp);
951  retval = 0;
952  } else if (ocs_strcmp(unqualified_name, "hlm_group_size") == 0) {
953  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hlm_group_size", "%d", hlm_group_size);
954  retval = 0;
955  } else if (ocs_strcmp(unqualified_name, "explicit_buffer_list") == 0) {
956  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "explicit_buffer_list", explicit_buffer_list);
957  retval = 0;
958  } else if (ocs_strcmp(unqualified_name, "hw_cmpl_context") == 0) {
959  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_cmpl_context", "%d", hw_cmpl_context);
960  retval = 0;
961  } else if (ocs_strcmp(unqualified_name, "external_loopback") == 0) {
962  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "external_loopback", external_loopback);
963  retval = 0;
964  } else if (ocs_strcmp(unqualified_name, "target_io_timer") == 0) {
965  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "target_io_timer", "%d", target_io_timer);
966  retval = 0;
967  } else if (ocs_strcmp(unqualified_name, "target_wqe_timer") == 0) {
968  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "target_wqe_timer", "%d", target_wqe_timer);
969  retval = 0;
970 #endif
971 #if defined(OCS_INCLUDE_RAMD)
972  } else if (ocs_strcmp(unqualified_name, "num_luns") == 0) {
973  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_luns", "%d", num_luns);
974  retval = 0;
975  } else if (ocs_strcmp(unqualified_name, "ramdisc_blocksize") == 0) {
976  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramdisc_blocksize", "%d", ramdisc_blocksize);
977  retval = 0;
978  } else if (ocs_strcmp(unqualified_name, "ramdisc_size") == 0) {
979  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ramdisc_size", ramdisc_size);
980  retval = 0;
981  } else if (ocs_strcmp(unqualified_name, "global_ramdisc") == 0) {
982  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "global_ramdisc", "%d", global_ramdisc);
983  retval = 0;
984  } else if (ocs_strcmp(unqualified_name, "p_type") == 0) {
985  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "p_type", "%d", p_type);
986  retval = 0;
987  } else if (ocs_strcmp(unqualified_name, "stub_res6_rel6") == 0) {
988  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "stub_res6_rel6", "%d", stub_res6_rel6);
989  retval = 0;
990  } else if (ocs_strcmp(unqualified_name, "esoc") == 0) {
991  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "esoc", "%d", esoc);
992  retval = 0;
993 #endif
994  }
995 
996  }
997 
998  ocs_mgmt_end_unnumbered_section(textbuf, "driver");
999 
1000  return retval;
1001 }
1002 
1003 void ocs_mgmt_driver_get_all(ocs_textbuf_t *textbuf, void *object)
1004 {
1005  ocs_mgmt_start_unnumbered_section(textbuf, "driver");
1006 
1007  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "initiator", initiator);
1008  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "target", target);
1009  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "logmask", "0x%x", logmask);
1010  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ctrlmask", "0x%x", ctrlmask);
1011  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "logdest", "%d", logdest);
1012  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "loglevel", "%d", loglevel);
1013  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "rq_threads", "%d", rq_threads);
1014  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramlog_size", "%d", ramlog_size);
1015  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "hal_war_version", hal_war_version);
1016  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_scsi_ios", "%d", num_scsi_ios);
1017  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "pm_state", ocs_pm_get_state_string(textbuf->ocs));
1018  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ddump_saved_size", "%d", ddump_saved_size);
1019  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "dif_separate", dif_separate);
1020  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "queue_topology", queue_topology);
1021  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "rq_selection_policy", "%d", rq_selection_policy);
1022  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "rr_quanta", "%d", rr_quanta);
1023  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "filter_def", filter_def);
1024  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "cq_process_limit", "%d", cq_process_limit);
1025  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "explicit_buffer_list", "%d", explicit_buffer_list);
1026  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "watchdog_timeout", "%d", watchdog_timeout);
1027  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "sliport_healthcheck", "%d", sliport_healthcheck);
1028  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "disable_fec", "%d", disable_fec);
1029  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ethernet_license", "%d", ethernet_license);
1030 #if defined(OCS_INCLUDE_FC)
1031  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "enable_dpp", "%d", enable_dpp);
1032  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "wwn_bump", wwn_bump);
1033  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "topology", "%d", topology);
1034  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "speed", "%d", speed);
1035  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "holdoff_link_online", holdoff_link_online);
1036  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_hlm", enable_hlm);
1037  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hlm_group_size", "%d", hlm_group_size);
1038  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "explicit_buffer_list", explicit_buffer_list);
1039  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_cmpl_context", "%d", hw_cmpl_context);
1040  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "external_loopback", external_loopback);
1041  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "target_io_timer", "%d", target_io_timer);
1042  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "target_wqe_timer", "%d", target_wqe_timer);
1043 #endif
1044 #if defined(OCS_INCLUDE_RAMD)
1045  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_vports", "%d", num_vports);
1046  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_luns", "%d", num_luns);
1047  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramdisc_blocksize", "%d", ramdisc_blocksize);
1048  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ramdisc_size", ramdisc_size);
1049  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "global_ramdisc", "%d", global_ramdisc);
1050  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "p_type", "%d", p_type);
1051  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramd_threading", "%d", ramd_threading);
1052  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "thread_cmds", "%d", thread_cmds);
1053  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "external_dif", external_dif);
1054  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "stub_res6_rel6", stub_res6_rel6);
1055  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "esoc", "%d", esoc);
1056 
1057 #endif
1058 #if defined(OCS_DISC_SPIN_DELAY)
1059  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "disk_spin_delay", "%d", disk_spin_delay);
1060 #endif
1061  /* Actions */
1062  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "gendump");
1063  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "fdb_gendump");
1064  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "dump_to_host");
1065  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "fdb_dump_to_host");
1066  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "clear_ramlog");
1067  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_sleep");
1068  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_prepare");
1069  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_hibernate");
1070  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "pm_resume");
1071  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "gen_saved_ddump");
1072 
1073  ocs_mgmt_end_unnumbered_section(textbuf, "driver");
1074 }
1075 
1076 int ocs_mgmt_driver_exec(char *parent, char *action_name, void *arg_in,
1077  uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length, void *object)
1078 {
1079  char qualifier[80];
1080  int retval = -1;
1081  ocs_t *ocs = (ocs_t *)object;
1082 
1083  ocs_snprintf(qualifier, sizeof(qualifier), "%s/driver", parent);
1084 
1085  /* If it doesn't start with my qualifier I don't know what to do with it */
1086  if (ocs_strncmp(action_name, qualifier, strlen(qualifier)) == 0) {
1087  char *unqualified_name = action_name + strlen(qualifier) +1;
1088 
1089  /* See if it's a value I can supply */
1090  if (ocs_strcmp(unqualified_name, "gendump") == 0) {
1091  retval = ocs_gendump(ocs, FW_CHIP_LEVEL_DUMP);
1092  }
1093  if (ocs_strcmp(unqualified_name, "fdb_gendump") == 0) {
1094  retval = ocs_gendump(ocs, FW_FUNC_DESC_DUMP);
1095  }
1096  if (ocs_strcmp(unqualified_name, "dump_to_host") == 0) {
1097  retval = ocs_dump_to_host(ocs, arg_out, arg_out_length, FW_CHIP_LEVEL_DUMP);
1098  }
1099  if (ocs_strcmp(unqualified_name, "fdb_dump_to_host") == 0) {
1100  retval = ocs_dump_to_host(ocs, arg_out, arg_out_length, FW_FUNC_DESC_DUMP);
1101  }
1102  if (ocs_strcmp(unqualified_name, "trunk_mode") == 0) {
1103  uint32_t trunk_mode;
1104  retval = -1;
1105  if (arg_in && arg_in_length) {
1106  if (!ocs_copy_from_user(&trunk_mode, arg_in,
1107  MIN(arg_in_length, sizeof(trunk_mode)))) {
1108  retval = ocs_set_fc_trunk_mode(ocs, trunk_mode);
1109  }
1110  }
1111  }
1112  if (ocs_strcmp(unqualified_name, "trunk_info") == 0) {
1113  uint32_t trunk_info;
1114  if (arg_out && arg_out_length) {
1115  retval = ocs_get_fc_trunk_info(ocs, &trunk_info);
1116  if (retval || ocs_copy_to_user(arg_out, &trunk_info,
1117  MIN(arg_out_length, sizeof(trunk_info)))) {
1118  retval = -EPERM;
1119  }
1120  } else {
1121  retval = -EINVAL;
1122  }
1123  }
1124  if (ocs_strcmp(unqualified_name, "link_loopback") == 0) {
1125  retval = ocs_run_link_loopback(ocs, arg_in, arg_in_length, arg_out, arg_out_length);
1126  }
1127  if (ocs_strcmp(unqualified_name, "pci_loopback") == 0) {
1128  retval = ocs_run_pci_loopback(ocs, arg_in, arg_in_length, arg_out, arg_out_length);
1129  }
1130  if (ocs_strcmp(unqualified_name, "fw_diag_log") == 0) {
1131  retval = ocs_ras_collect_diag_logs(ocs, arg_in, arg_in_length, arg_out, arg_out_length);
1132  }
1133  if (ocs_strcmp(unqualified_name, "set_loopback") == 0) {
1134  uint32_t local_arg_in;
1135  retval = -1;
1136  if (arg_in && arg_in_length) {
1137  if (!ocs_copy_from_user(&local_arg_in, arg_in,
1138  MIN(arg_in_length, sizeof(local_arg_in)))) {
1139  retval = ocs_set_loopback_mode(ocs, local_arg_in);
1140  }
1141  }
1142  }
1143  if (ocs_strcmp(unqualified_name, "get_link_state") == 0) {
1144  ocs_xport_stats_t link_status;
1145 
1146  retval = ocs_xport_status(ocs->xport, OCS_XPORT_PORT_STATUS, &link_status);
1147  if (!retval && arg_out) {
1148  if (ocs_copy_to_user(arg_out, &link_status.value, sizeof(uint32_t))) {
1149  retval = -1;
1150  }
1151  }
1152  }
1153  if (ocs_strcmp(unqualified_name, "set_link_state") == 0) {
1154  uint32_t local_arg_in;
1155  retval = -1;
1156  if (arg_in && arg_in_length) {
1157  if (!ocs_copy_from_user(&local_arg_in, arg_in,
1158  MIN(arg_in_length, sizeof(local_arg_in)))) {
1159  retval = ocs_xport_control(ocs->xport, local_arg_in);
1160  }
1161  }
1162  }
1163 
1164  if (ocs_strcmp(unqualified_name, "clear_ramlog") == 0) {
1165  char local_arg_in[128];
1166  int clear_start_of_day = 0;
1167  int clear_recent = 0;
1168  if (arg_in) {
1169  if (ocs_copy_from_user(local_arg_in, arg_in,
1170  MIN(arg_in_length, sizeof(local_arg_in)-1))) {
1171  ocs_log_warn(ocs, "Error: copy arg_in from user failed\n");
1172  return -1;
1173  }
1174 
1175  local_arg_in[sizeof(local_arg_in)-1] = 0;
1176  if (ocs_strcmp(local_arg_in, "recent") == 0) {
1177  clear_recent = 1;
1178  } else if (ocs_strcmp(local_arg_in, "start_of_day") == 0) {
1179  clear_start_of_day = 1;
1180  } else if (ocs_strcmp(local_arg_in, "all") == 0) {
1181  clear_recent = 1;
1182  clear_start_of_day = 1;
1183  }
1184  } else {
1185  clear_recent = 1;
1186  clear_start_of_day = 1;
1187  }
1188 
1189  ocs_log_debug(ocs, "Clear ramlog:%s%s\n", clear_start_of_day ? " start_of_day" : "",
1190  clear_recent ? " recent" : "");
1191 
1192  ocs_ramlog_clear(ocs, ocs->ramlog, clear_start_of_day, clear_recent);
1193  retval = 0;
1194  }
1195  if (ocs_strcmp(unqualified_name, "pm_prepare") == 0) {
1196  retval = ocs_pm_request(ocs, OCS_PM_PREPARE, NULL, NULL);
1197  }
1198  if (ocs_strcmp(unqualified_name, "pm_sleep") == 0) {
1199  retval = ocs_pm_request(ocs, OCS_PM_SLEEP, NULL, NULL);
1200  }
1201  if (ocs_strcmp(unqualified_name, "pm_hibernate") == 0) {
1202  retval = ocs_pm_request(ocs, OCS_PM_HIBERNATE, NULL, NULL);
1203  }
1204  if (ocs_strcmp(unqualified_name, "pm_resume") == 0) {
1205  retval = ocs_pm_request(ocs, OCS_PM_RESUME, NULL, NULL);
1206  }
1207  if (ocs_strcmp(unqualified_name, "gen_saved_ddump") == 0) {
1208  retval = ocs_save_ddump(ocs, 0xff, ~0);
1209  }
1210 
1211  if (ocs_strcmp(unqualified_name, "lancer_temp") == 0) {
1212  retval = ocs_read_temperature_lancer(ocs, arg_out, arg_out_length);
1213  if (retval != 0) {
1214  ocs_log_err(ocs, "Failed to read temperature\n");
1215  }
1216  }
1217  }
1218 
1219  return retval;
1220 }
1221 
1222 static void
1224 {
1225  ocs_log_info(NULL, "%s: driver version %s\n", DRV_NAME, DRV_VERSION);
1226 
1227  ocs_log_info(NULL, " Module parameters:\n");
1228  ocs_log_info(NULL, " Initiator = %d\n", initiator);
1229  ocs_log_info(NULL, " Target = %d\n", target);
1230  ocs_log_info(NULL, " ctrlmask = 0x%04x\n", ctrlmask);
1231  ocs_log_info(NULL, " loglevel = %d\n", loglevel);
1232  ocs_log_info(NULL, " logmask = 0x%04x\n", logmask);
1233  ocs_log_info(NULL, " ramlog_size = %d\n", ramlog_size);
1234  ocs_log_info(NULL, " rq_threads = %d\n", rq_threads);
1235  ocs_log_info(NULL, " wwn_bump = %s\n", wwn_bump);
1236  ocs_log_info(NULL, " topology = %d\n", topology);
1237  ocs_log_info(NULL, " speed = %d\n", speed);
1238  ocs_log_info(NULL, " holdoff_link_online = %d\n", holdoff_link_online);
1239  ocs_log_info(NULL, " enable_hlm = %d\n", enable_hlm);
1240  ocs_log_info(NULL, " hlm_group_size = %d\n", hlm_group_size);
1241  ocs_log_info(NULL, " max_remote_nodes = %d\n", max_remote_nodes);
1242  ocs_log_info(NULL, " ethernet_license = %d\n", ethernet_license);
1243  ocs_log_info(NULL, " num_scsi_ios = %d\n", num_scsi_ios);
1244  ocs_log_info(NULL, " dif_separate = %d\n", dif_separate);
1245  ocs_log_info(NULL, " tow_feature = %d\n", tow_feature);
1246  ocs_log_info(NULL, " tow_io_size = %d\n", tow_io_size);
1247  ocs_log_info(NULL, " tow_xri_cnt = %d\n", tow_xri_cnt);
1248  ocs_log_info(NULL, " queue_topology = %s\n", queue_topology);
1249  ocs_log_info(NULL, " rq_selection_policy = %d\n", rq_selection_policy);
1250  ocs_log_info(NULL, " rr_quanta = %d\n", rr_quanta);
1251  ocs_log_info(NULL, " filter_ref = %s\n", filter_def);
1252  ocs_log_info(NULL, " cq_process_limit = %d\n", cq_process_limit);
1253  ocs_log_info(NULL, " explicit_buffer_list = %d\n", explicit_buffer_list);
1254  ocs_log_info(NULL, " external_loopback = %d\n", external_loopback);
1255  ocs_log_info(NULL, " target_io_timer = %d\n", target_io_timer);
1256  ocs_log_info(NULL, " target_wqe_timer = %d\n", target_wqe_timer);
1257  ocs_log_info(NULL, " ddump_saved_size = %d\n", ddump_saved_size);
1258  ocs_log_info(NULL, " hal_war_version = %s\n", hal_war_version);
1259  ocs_log_info(NULL, " hw_cmpl_context = %d\n", hw_cmpl_context);
1260  ocs_log_info(NULL, " watchdog_timeout = %d\n", watchdog_timeout);
1261  ocs_log_info(NULL, " heartbeat_cpu_mask = 0x%lx\n", heartbeat_cpu_mask);
1262  ocs_log_info(NULL, " sliport_healthcheck = %d\n", sliport_healthcheck);
1263  ocs_log_info(NULL, " disable_fec = %d\n", disable_fec);
1264  ocs_log_info(NULL, " enable_dpp = %d\n", enable_dpp);
1265  ocs_log_info(NULL, " sliport_pause_errors = %s\n", sliport_pause_errors);
1266  ocs_log_info(NULL, " enable_bbcr = %d\n", enable_bbcr);
1267  ocs_log_info(NULL, " fw_dump_type = %d\n", fw_dump_type);
1268  ocs_log_info(NULL, " enable_auto_recovery = %d\n", enable_auto_recovery);
1269  ocs_log_info(NULL, " cfg_suppress_rsp = %d\n", cfg_suppress_rsp);
1270 #if defined(OCS_DISC_SPIN_DELAY)
1271  ocs_log_info(NULL, " disk_spin_delay = %d\n", disk_spin_delay);
1272 #endif
1273 
1274 #if defined(OCS_INCLUDE_RAMD)
1275  ocs_log_info(NULL, " num_vports = %d\n", num_vports);
1276  ocs_log_info(NULL, " p_type = %d\n", p_type);
1277  ocs_log_info(NULL, " ramdisc_size = %s\n", ramdisc_size);
1278  ocs_log_info(NULL, " ramdisc_blocksize = %d\n", ramdisc_blocksize);
1279  ocs_log_info(NULL, " num_luns = %d\n", num_luns);
1280  ocs_log_info(NULL, " global_ramdisc = %d\n", global_ramdisc);
1281  ocs_log_info(NULL, " stub_res6_rel6 = %d\n", stub_res6_rel6);
1282  ocs_log_info(NULL, " ramd_threading = %d\n", ramd_threading);
1283  ocs_log_info(NULL, " thread_cmds = %d\n", thread_cmds);
1284  ocs_log_info(NULL, " external_dif = %s\n", external_dif);
1285  ocs_log_info(NULL, " esoc = %d\n", esoc);
1286 #endif
1287 }
1288 
1289 int32_t
1290 ocs_set_fc_trunk_mode(ocs_t *ocs, uint32_t trunk_mode)
1291 {
1292  int32_t rc;
1293 
1294  rc = ocs_hal_set_trunk_mode(&ocs->hal, trunk_mode);
1295  if (rc) {
1296  ocs_log_err(ocs, "failed to set trunk mode\n");
1297  } else {
1298  ocs_log_debug(ocs, "Trunk mode been set successfully\n");
1299  }
1300  return rc;
1301 }
1302 
1303 int32_t
1304 ocs_get_fc_trunk_info(ocs_t *ocs, uint32_t *trunk_info)
1305 {
1306  int32_t rc;
1307 
1308  rc = ocs_hal_get_trunk_info(&ocs->hal, trunk_info);
1309  if (rc) {
1310  ocs_log_err(ocs, "failed to get trunk info\n");
1311  } else {
1312  ocs_log_debug(ocs, "Trunk info obtained successfully\n");
1313  }
1314  return rc;
1315 }
1316 
1317 int
1318 ocs_set_loopback_mode(ocs_t *ocs, uint32_t loopback_mode)
1319 {
1320  int rc = 0;
1321 
1322  if (loopback_mode == INTERNAL_LOOPBACK) {
1323  ocs_log_debug(ocs, "Setting port to internal loopback mode\n");
1324  } else if (loopback_mode == EXTERNAL_LOOPBACK) {
1325  ocs_log_debug(ocs, "Setting port to external loopback mode\n");
1326  } else {
1327  ocs_log_debug(ocs, "Unsupported loopback mode: %d\n", loopback_mode);
1328  rc = -1;
1329  goto exit_set_loopback_mode;
1330  }
1331 
1332  ocs->external_loopback = 1;
1333  rc = ocs_hal_set_loopback_mode(&ocs->hal, loopback_mode);
1334  if (rc) {
1335  ocs_log_err(ocs, "failed to set loopback mode\n");
1336  } else {
1337  ocs_log_debug(ocs, "Loopback mode been set successfully\n");
1338  }
1339 
1340 exit_set_loopback_mode:
1341  return rc;
1342 }
1343 
1344 int
1345 ocs_run_link_loopback(ocs_t *ocs, void *user_tx_buf, uint32_t user_tx_buflen, void *user_rx_buf, uint32_t rx_buf_len)
1346 {
1347  ocs_node_t *node = NULL;
1348  int rc = 0;
1349  void *tx_buf = NULL;
1350  void *rx_buf = NULL;
1351  ocs_io_t *els = NULL;
1352 
1353  if ((user_tx_buflen == 0) || (rx_buf_len == 0) || (user_tx_buflen != rx_buf_len)) {
1354  ocs_log_test(ocs, "Error: loopback tx/rx buffer length is invalid\n");
1355  rc = -1;
1356  goto free_and_return;
1357  }
1358 
1359  if (!user_tx_buf || !user_rx_buf) {
1360  ocs_log_test(ocs, "Error: loopback either tx data or rx buffer not provided\n");
1361  rc = -1;
1362  goto free_and_return;
1363  }
1364 
1365  tx_buf = ocs_malloc(ocs, user_tx_buflen , OCS_M_ZERO | OCS_M_NOWAIT);
1366  if (tx_buf == NULL) {
1367  ocs_log_err(ocs, "Failed to allocate buffer for TX frame\n");
1368  rc = -1;
1369  goto free_and_return;
1370  }
1371 
1372  rx_buf = ocs_malloc(ocs, rx_buf_len , OCS_M_ZERO | OCS_M_NOWAIT);
1373  if (rx_buf == NULL) {
1374  ocs_log_err(ocs, "Failed to allocate buffer for TX frame\n");
1375  rc = -1;
1376  goto free_and_return;
1377  }
1378 
1379  if (ocs_copy_from_user(tx_buf, user_tx_buf, user_tx_buflen)) {
1380  ocs_log_err(ocs, "Failed to copy user data into TX buf\n");
1381  rc = -1;
1382  goto free_and_return;
1383  }
1384 
1385  if (ocs->domain) {
1386  node = ocs_node_find(ocs->domain->sport, 1);
1387  }
1388 
1389  if (node == NULL) {
1390  ocs_log_err(ocs, "Failed to find node for loopback test\n");
1391  rc = -1;
1392  goto free_and_return;
1393  }
1394 
1395  els = ocs_ns_send_loopback_frame(node, tx_buf, user_tx_buflen, rx_buf, rx_buf_len, LOOPBACK_FRAME_TIMEOUT_SEC, 0, NULL, NULL);
1396  if (els == NULL) {
1397  ocs_log_err(ocs, "loopback els IO submission failed\n");
1398  rc = -1;
1399  goto free_and_return;
1400  }
1401 
1402  if (ocs_sem_p(&els->loopback_evt_data.wait_io_sem, (LOOPBACK_FRAME_TIMEOUT_SEC + 1) * 1000 * 1000) != 0) {
1403  ocs_log_err(ocs, "sem failed. loopback frame not received\n");
1404  els->loopback_evt_data.loopback_rx_data = NULL;
1405  rc = -1;
1406  goto free_and_return;
1407  }
1408 
1409  if (ocs_copy_to_user(user_rx_buf, rx_buf, rx_buf_len)) {
1410  ocs_log_err(ocs, "Failed to copy RX data into user buf\n");
1411  rc = -1;
1412  goto free_and_return;
1413  }
1414 
1415 free_and_return:
1416  ocs->external_loopback = 0;
1417  if (tx_buf) {
1418  ocs_free(ocs, tx_buf, user_tx_buflen);
1419  }
1420  if (rx_buf) {
1421  ocs_free(ocs, rx_buf, rx_buf_len);
1422  }
1423  if (els) {
1424  ocs_ref_put(&els->ref);
1425  }
1426  return rc;
1427 }
1428 
1429 int
1430 ocs_run_pci_loopback(ocs_t *ocs, void *user_tx_buf, uint32_t user_tx_buflen,
1431  void *user_rx_buf, uint32_t user_rx_buf_len)
1432 {
1433  int rc = 0;
1434  void *tx_buf = NULL;
1435  void *rx_buf = NULL;
1436 
1437  if ((user_tx_buflen == 0) || (user_rx_buf_len == 0) ||
1438  (user_tx_buflen != user_rx_buf_len)) {
1439  ocs_log_test(ocs, "Error: loopback tx/rx buffer length is invalid\n");
1440  rc = -1;
1441  goto free_and_return;
1442  }
1443 
1444  if (!user_tx_buf || !user_rx_buf) {
1445  ocs_log_test(ocs, "Error: loopback either tx data or rx buffer not provided\n");
1446  rc = -1;
1447  goto free_and_return;
1448  }
1449 
1450  tx_buf = ocs_malloc(ocs, user_tx_buflen , OCS_M_ZERO | OCS_M_NOWAIT);
1451  if (tx_buf == NULL) {
1452  ocs_log_err(ocs, "Failed to allocate buffer for TX frame\n");
1453  rc = -1;
1454  goto free_and_return;
1455  }
1456 
1457  rx_buf = ocs_malloc(ocs, user_rx_buf_len , OCS_M_ZERO | OCS_M_NOWAIT);
1458  if (rx_buf == NULL) {
1459  ocs_log_err(ocs, "Failed to allocate buffer for TX frame\n");
1460  rc = -1;
1461  goto free_and_return;
1462  }
1463 
1464  if (ocs_copy_from_user(tx_buf, user_tx_buf, user_tx_buflen)) {
1465  ocs_log_err(ocs, "Failed to copy user data into TX buf\n");
1466  rc = -1;
1467  goto free_and_return;
1468  }
1469 
1470  rc = ocs_hal_run_biu_diag(&ocs->hal, tx_buf, user_tx_buflen,
1471  rx_buf, user_rx_buf_len);
1472  if (rc) {
1473  ocs_log_err(ocs, "BIU DIAG MBOX command is failed\n");
1474  goto free_and_return;
1475  }
1476 
1477  if (ocs_copy_to_user(user_rx_buf, rx_buf, user_rx_buf_len)) {
1478  ocs_log_err(ocs, "Failed to copy RX data into user buf\n");
1479  rc = -1;
1480  goto free_and_return;
1481  }
1482 
1483 free_and_return:
1484  if (tx_buf) {
1485  ocs_free(ocs, tx_buf, user_tx_buflen);
1486  }
1487  if (rx_buf) {
1488  ocs_free(ocs, rx_buf, user_rx_buf_len);
1489  }
1490  return rc;
1491 }
1492 
1493 int
1494 ocs_ras_collect_diag_logs(ocs_t *ocs, void *user_tx_buf, uint32_t user_tx_buflen, void *user_rx_buf, uint32_t rx_buf_len)
1495 {
1496  int rc = 0;
1497  void *rx_buf = NULL;
1498  int32_t buf_len;
1499 
1500  if (!rx_buf_len || !user_rx_buf) {
1501  ocs_log_err(ocs, "Error: tx/rx buffer is invalid\n");
1502  return -EINVAL;
1503  }
1504 
1505  buf_len = rx_buf_len;
1506 
1507  rx_buf = ocs_vmalloc(ocs, buf_len, OCS_M_ZERO);
1508  if (rx_buf == NULL) {
1509  ocs_log_err(ocs, "unable to allocate memory\n");
1510  return -ENOMEM;
1511  }
1512 
1513  buf_len = ocs_ras_copy_logs(ocs, rx_buf + sizeof(uint32_t), buf_len - sizeof(uint32_t));
1514  *((uint32_t *)rx_buf) = buf_len;
1515  if (buf_len > 0) {
1516  if (ocs_copy_to_user(user_rx_buf, rx_buf, buf_len + sizeof(uint32_t))) {
1517  ocs_log_err(ocs, "Failed to copy buffer for fw diag log\n");
1518  rc = -EPERM;
1519  } else {
1520  rc = 0;
1521  }
1522  } else {
1523  rc = -EINVAL;
1524  }
1525 
1526  ocs_vfree(ocs, rx_buf, rx_buf_len);
1527  return rc;
1528 }
const char * ocs_pm_get_state_string(ocs_t *ocs)
Return driver power state as an ascii string.
Definition: ocs_pm.c:141
uint32_t ocs_instance(void *os)
Return instance index of an opaque ocs structure.
static void ocs_driver_print_module_params(void)
static void ocs_device_interrupt_handler(ocs_t *ocs, uint32_t vector)
interrupt handler
#define OCS_HAL_OBJECT_G5
Definition: ocs_hal.h:1461
int ocs_run_link_loopback(ocs_t *ocs, void *tx_buf, uint32_t tx_buflen, void *rx_buf, uint32_t rx_buflen)
int32_t ocs_scsi_tgt_driver_init(void)
Driver-wide initialization for the target-server.
Definition: ocs_ramd.c:354
static void ocs_capture_hal_global_params(void)
int ocs_ras_copy_logs(ocs_t *ocs, void *user_buf, int32_t user_buf_len)
Definition: ocs_ras.c:237
void ocs_device_shutdown(void)
Perform driver wide shutdown actions.
int32_t ocs_scsi_ini_driver_init(int32_t initiator)
Initialize initiator client.
Definition: ocs_ini_stub.c:51
#define LOOPBACK_FRAME_TIMEOUT_SEC
int32_t ocs_device_interrupts_required(ocs_t *ocs)
return the number of interrupts required per HBA
int ocs_set_loopback_mode(ocs_t *ocs, uint32_t arg_in)
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.
uint8_t revision[32]
Definition: ocs_hal.h:1471
int32_t ocs_scsi_tgt_driver_exit(void)
Driver-wide clean-up for the target-server.
Definition: ocs_ramd.c:401
uint64_t g_app_watchdog_cpu_mask
uint32_t ocs_hal_qtop_eq_count(ocs_hal_t *hal)
Return count of EQs for a queue topology object.
void ocs_hal_free_dump_to_host_buffers(ocs_hal_t *hal)
Definition: ocs_hal.c:7561
ocs_hal_global_t hal_global
Definition: ocs_hal.c:78
void ocs_mgmt_driver_get_all(ocs_textbuf_t *textbuf, void *driver)
void ocs_xport_config_stats_timer(void *arg)
Get FC link and host Statistics periodically.
Definition: ocs_xport.c:1354
void ocs_device_free(ocs_t *ocs)
free ocs device
static void ocs_device_lock_init(ocs_t *ocs)
Definition: ocs_drv_fc.h:187
void ocs_fw_err_recovery_stop(void)
Stop FW error recovery thread.
Definition: ocs_recovery.c:191
#define SLI4_MBOX_EXT_STATUS_OBJ_UNSUPPORTED_FIRMWARE
Definition: sli4.h:462
#define DRV_VERSION
Definition: ocs.h:49
uint32_t fw_diag_log_size
Definition: ocs_hal.h:1268
static ocs_mgmt_functions_t driver_mgmt_functions
#define MGMT_MODE_EX
Definition: ocs_mgmt.h:49
int32_t ocs_xport_detach(ocs_xport_t *xport)
Detaches the transport from the device.
Definition: ocs_xport.c:735
ocs_hal_rtn_e ocs_hal_set_loopback_mode(ocs_hal_t *hal, uint32_t type)
Set the Lancer dump location.
Definition: ocs_hal.c:7772
void ocs_fw_dump_init(ocs_t *ocs, int32_t fw_dump_type)
Initialize fw dump context.
Definition: ocs_recovery.c:762
static void ocs_device_lock_free(ocs_t *ocs)
Definition: ocs_drv_fc.h:192
const char * name
Definition: ocs_ddump.h:54
static uint32_t thread_cmds
int32_t ocs_device_detach(ocs_t *ocs)
free resources when pci device detach
#define DRV_NAME
Definition: ocs.h:48
int ocs_mgmt_driver_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length, void *driver)
ocs_node_t * ocs_node_find(ocs_sport_t *sport, uint32_t port_id)
Find an FC node structure given the FC port ID.
Definition: ocs_node.c:202
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.
int32_t ocs_xport_attach(ocs_xport_t *xport)
Do as much allocation as possible, but do not initialization the device.
Definition: ocs_xport.c:193
int32_t ocs_save_ddump(ocs_t *ocs, uint32_t flags, uint32_t qentries)
Capture and save ddump.
Definition: ocs_ddump.c:820
uint32_t fw_diag_log_level
Definition: ocs_hal.h:1269
void ocs_textbuf_free(ocs_t *ocs, ocs_textbuf_t *textbuf)
Definition: ocs_textbuf.c:213
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.
int ocs_ras_collect_diag_logs(ocs_t *ocs, void *user_tx_buf, uint32_t user_tx_buflen, void *user_rx_buf, uint32_t rx_buf_len)
int ocs_request_firmware_update(ocs_t *ocs)
int ocs_firmware_write(ocs_t *ocs, const u8 *buf, size_t buf_len, uint8_t *change_status)
#define OCS_RAS_LOGICAL_BUFFER_SIZE_MIN
Definition: ocs_ras.h:53
void ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog)
Free a ramlog buffer.
Definition: ocs_ramlog.c:116
int32_t ocs_xport_control(ocs_xport_t *xport, ocs_xport_ctrl_e cmd,...)
Perform transport attach function.
Definition: ocs_xport.c:866
#define ocs_list_init(head, type, link)
Definition: ocs_list.h:113
int32_t ocs_device_init_complete(void)
Perform device initialization complete.
int32_t ocs_fw_err_recovery_setup(void)
Create a FW error recovery thread.
Definition: ocs_recovery.c:742
static ocs_t * ocs_devices[MAX_OCS_DEVICES]
int32_t ocs_start_event_processing(ocs_os_t *ocs_os)
#define OCS_RAS_LOGICAL_BUFFER_SIZE_MAX
Definition: ocs_ras.h:54
#define INTERNAL_LOOPBACK
uint32_t value
Definition: ocs_xport.h:170
int32_t ocs_pm_request(ocs_t *ocs, ocs_pm_msg_e msg, int32_t(*callback)(ocs_t *ocs, int32_t status, void *arg), void *arg)
Handle Power Management Request.
Definition: ocs_pm.c:81
int ocs_run_pci_loopback(ocs_t *ocs, void *tx_buf, uint32_t tx_buflen, void *rx_buf, uint32_t rx_buflen)
void ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
Generate the end of a section in a management XML document.
int32_t ocs_device_attach(ocs_t *ocs)
Initialize resources when pci devices attach.
int32_t ocs_scsi_host_ml_registered(ocs_t *ocs)
const char * ocs_display_name(void *os)
return OCS instance display name
uint32_t magic_number
Definition: ocs_hal.h:1467
int32_t ocs_xport_initialize(ocs_xport_t *xport)
Initializes the device.
Definition: ocs_xport.c:509
ocs_t * ocs_get_instance(uint32_t index)
return pointer to ocs structure given instance index
#define OCS_RAS_FW_LOG_LEVEL_MAX
Definition: ocs_ras.h:57
ocs_mgmt_get_list_handler get_list_handler
Definition: ocs_mgmt.h:83
#define FW_DUMP_TYPE_DUMPTOHOST
Definition: ocs_gendump.h:64
#define FW_FUNC_DESC_DUMP
Definition: ocs_gendump.h:56
#define EXTERNAL_LOOPBACK
int32_t ocs_fw_reset(ocs_t *ocs)
Definition: ocs_gendump.c:86
const char * queue_topology_string
Definition: ocs_hal.h:1267
#define MGMT_MODE_RD
Definition: ocs_mgmt.h:47
ocs_t * ocs
Definition: ocs_textbuf.h:49
int32_t ocs_dump_to_host(ocs_t *ocs, void *buf, uint32_t buflen, uint8_t dump_level)
Create a Lancer dump into a memory buffer.
Definition: ocs_recovery.c:581
int32_t ocs_scsi_ini_driver_exit(int32_t initiator)
initiator client exit
Definition: ocs_ini_stub.c:103
#define FW_CHIP_LEVEL_DUMP
Definition: ocs_gendump.h:55
int ocs_mgmt_driver_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *driver)
#define OCS_RAMLOG_DEFAULT_BUFFERS
Definition: ocs_ramlog.h:46
void ocs_mgmt_driver_list(ocs_textbuf_t *textbuf, void *driver)
ocs_io_t * ocs_ns_send_loopback_frame(ocs_node_t *node, void *buf, uint32_t size, void *rx_buf, uint32_t rx_buf_size, uint32_t timeout_sec, uint32_t retries, els_cb_t cb, void *cbarg)
Definition: ocs_els.c:2118
int ocs_set_fc_trunk_mode(ocs_t *ocs, uint32_t trunk_mode)
int32_t ocs_read_temperature_lancer(ocs_t *ocs, void *buf, uint32_t buf_len)
Definition: ocs_mgmt.c:1083
ocs_hal_rtn_e ocs_hal_get_trunk_info(ocs_hal_t *hal, uint32_t *trunk_info)
Get trunking mode information.
Definition: ocs_hal.c:6987
int32_t ocs_gendump(ocs_t *ocs, uint8_t dump_level)
Definition: ocs_recovery.c:480
int32_t ocs_hal_process(ocs_hal_t *hal, uint32_t vector, uint32_t max_isr_time_msec)
Definition: ocs_hal.c:2530
void ocs_stop_event_processing(ocs_os_t *ocs_os)
ocs_xport_t * ocs_xport_alloc(ocs_t *ocs)
Allocate a transport object.
Definition: ocs_xport.c:71
#define FW_WRITE_BUFSIZE
PARAM_LIST int32_t ocs_device_init(void)
void ocs_xport_free(ocs_xport_t *xport)
Free a transport object.
Definition: ocs_xport.c:1394
void * ocs_device_alloc(uint32_t nid)
int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
get driver wide property value
ocs_hal_rtn_e ocs_hal_setup(ocs_hal_t *hal, ocs_os_handle_t os, sli4_port_type_e port_type)
Set up the Hardware Abstraction Layer module.
Definition: ocs_hal.c:606
#define ocs_assert(cond,...)
Definition: ocs_debug.h:176
ocs_hal_rtn_e ocs_hal_run_biu_diag(ocs_hal_t *hal, void *tx_buff, size_t tx_buff_len, void *rx_buff, size_t rx_buff_len)
Run Diagnostic PCI Loopback test.
Definition: ocs_hal.c:7801
ocs_hal_rtn_e ocs_hal_clear_dump_location(ocs_hal_t *hal)
Clear the Lancer dump location.
Definition: ocs_hal.c:7980
int32_t ocs_textbuf_alloc(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t length)
Definition: ocs_textbuf.c:105
int ocs_get_fc_trunk_info(ocs_t *ocs, uint32_t *trunk_config)
void * ocs_hal_get_ptr(ocs_hal_t *hal, ocs_hal_property_e prop)
Definition: ocs_hal.c:2175
static void ocs_fw_write_cb(int32_t status, int32_t ext_status, uint32_t actual_write_length, uint32_t change_status, void *arg)
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.
void ocs_ramlog_clear(ocs_t *ocs, ocs_ramlog_t *ramlog, int clear_start_of_day, int clear_recent)
Clear a ramlog buffer.
Definition: ocs_ramlog.c:148
#define ocs_list_foreach(list, item)
Iterate a linked list.
Definition: ocs_list.h:428
ocs_ramlog_t * ocs_ramlog_init(ocs_t *ocs, uint32_t buffer_len, uint32_t buffer_count)
Allocate a ramlog buffer.
Definition: ocs_ramlog.c:65
#define OCS_HAL_OBJECT_G6
Definition: ocs_hal.h:1462
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.
void ocs_device_shutdown_complete(void)
Perform driver wide shutdown complete actions.
ocs_hal_rtn_e ocs_hal_set_trunk_mode(ocs_hal_t *hal, uint32_t trunk_mode)
Set trunking mode.
Definition: ocs_hal.c:6951
#define FW_DUMP_TYPE_FLASH
Definition: ocs_gendump.h:65
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