Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_driver.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 #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_pm.h"
39 #if defined(OCS_INCLUDE_RAMD)
40 #include "ocs_ramd.h"
41 #endif
42 
43 #include "ocs_params.h"
44 
45 static void ocs_device_interrupt_handler(ocs_t *ocs, uint32_t vector);
46 
47 #if defined(OCS_INCLUDE_RAMD)
48 static int32_t ocs_mgmt_read_block(ocs_t *ocs, char *, void *, uint32_t , void *, uint32_t);
49 #endif
50 
51 void ocs_mgmt_driver_list(ocs_textbuf_t *textbuf, void *driver);
52 void ocs_mgmt_driver_get_all(ocs_textbuf_t *textbuf, void *driver);
53 int ocs_mgmt_driver_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *driver);
54 int ocs_mgmt_driver_exec(char *parent, char *action, void *arg_in, uint32_t arg_in_length,
55  void *arg_out, uint32_t arg_out_length, void *driver);
56 
59  .get_handler = ocs_mgmt_driver_get,
60  .get_all_handler = ocs_mgmt_driver_get_all,
61  .exec_handler = ocs_mgmt_driver_exec,
62 };
63 
64 /**
65  * @brief Perform driver wide initialization
66  *
67  * This function is called prior to enumerating PCI devices, with subsequent calls
68  * to ocs_device_attach. For OCS, this function invokes the back end functions
69  * ocs_scsi_tgt_driver_init(), and ocs_scsi_ini_driver_init()
70  *
71  * @return returns 0 for success, a negative error code value for failure.
72  */
73 int32_t
75 {
76  int32_t rc;
77 
78  ocs_thread_init();
79 
80  /* driver-wide init for target-server */
81  if (target) {
83  if (rc) {
84  ocs_log_err(NULL, "ocs_scsi_tgt_init failed rc=%d\n", rc);
85  return -1;
86  }
87  }
88 
89  /* driver-wide init for initiator-client */
90  if (initiator) {
91  rc = ocs_scsi_ini_driver_init(initiator);
92  if (rc) {
93  ocs_log_err(NULL, "ocs_scsi_ini_init failed rc=%d\n", rc);
95  return -ENOMEM;
96  }
97  }
98  return 0;
99 }
100 
101 /**
102  * @brief Perform device initialization complete
103  *
104  * This function is called after all PCI device/functions have been enumerated.
105  *
106  * @return returns 0 for success, a negative error code value for failure.
107  */
108 int32_t
110 {
111  return 0;
112 }
113 
114 /**
115  * @brief Perform driver wide shutdown actions
116  *
117  * This function is called prior to detatching devices during a driver
118  * unload.
119  *
120  * @return none
121  */
122 void
124 {
125 }
126 
127 /**
128  * @brief Perform driver wide shutdown complete actions
129  *
130  * This function is called shutdown for all devices has completed
131  *
132  * @return none
133  */
134 void
136 {
137  if (initiator) {
138  ocs_scsi_ini_driver_exit(initiator);
139  }
140  if (target) {
142  }
143 }
144 
145 /*
146  * @brief Allocate ocs device.
147  *
148  * @param nid Numa node ID
149  *
150  * @return Returns a pointer to an ocs_t on success, NULL on failure
151  */
152 
153 void *ocs_device_alloc(int32_t nid)
154 {
155  ocs_t *ocs = NULL;
156  uint32_t i;
157 
158 #if defined(OCS_INCLUDE_ISCSI)
159  if (initiator && (hw_cmpl_context == OCS_HW_CMPL_CONTEXT_THREAD)) {
160  ocs_log_test(NULL, "iSCSI initiator requires tasklets, setting hw_cmpl_context to %d\n",
161  OCS_HW_CMPL_CONTEXT_TASKLET);
162  hw_cmpl_context = OCS_HW_CMPL_CONTEXT_TASKLET;
163  }
164 #endif
165 
166  /* Allocate memory using nid only if it has valid NUMA node avalible*/
167  if (nid < 0) {
168  ocs = ocs_malloc(NULL, sizeof(*ocs), OCS_M_NOWAIT | OCS_M_ZERO);
169  } else {
170  ocs = ocs_malloc_nid(nid, sizeof(*ocs), OCS_M_NOWAIT | OCS_M_ZERO);
171  }
172  if (ocs != NULL) {
173  for (i = 0; i < ARRAY_SIZE(ocs_devices); i ++) {
174  if (ocs_devices[i] == NULL) {
175  ocs->instance_index = i;
176  ocs_devices[i] = ocs;
177  break;
178  }
179  }
180 
181  if (i == ARRAY_SIZE(ocs_devices)) {
182  ocs_log_err(NULL, "failed\n");
183  ocs_free(ocs, ocs, sizeof(*ocs));
184  ocs = NULL;
185  } else {
186  /* If enabled, initailize a RAM logging buffer */
187  if (logdest & 2) {
188  ocs->ramlog = ocs_ramlog_init(ocs, ramlog_size/OCS_RAMLOG_DEFAULT_BUFFERS,
190  /* If NULL was returned, then we'll simply skip using the ramlog but */
191  /* set logdest to 1 to ensure that we at least get default logging. */
192  if (ocs->ramlog == NULL) {
193  logdest = 1;
194  }
195  }
196 
197  /* initialize a saved ddump */
198  if (ddump_saved_size) {
199  if (ocs_textbuf_alloc(ocs, &ocs->ddump_saved, ddump_saved_size)) {
200  ocs_log_err(ocs, "failed to allocate memory for saved ddump\n");
201  }
202  }
203 
204 #if defined(ENABLE_LOCK_DEBUG)
205  ocs_list_init(&ocs->ocs_os.locklist, ocs_lock_t, link);
206  ocs_lock_init(NULL, &ocs->ocs_os.locklist_lock, "locklist_lock[%d]", ocs->instance_index);
207 #endif
208  ocs_list_init(&ocs->domain_list, ocs_domain_t, link);
209  ocs->ocs_os.interrupt_cb = ocs_device_interrupt_handler;
211  ocs->drv_ocs.attached = FALSE;
212  ocs->ocs_os.hw_cmpl_context = hw_cmpl_context;
213  ocs->mgmt_functions = &driver_mgmt_functions;
214  }
215  }
216  return ocs;
217 }
218 
219 /**
220  * @brief free ocs device
221  *
222  * @param ocs pointer to ocs structure
223  *
224  * @return none
225  */
226 
227 void ocs_device_free(ocs_t *ocs)
228 {
229  if (ocs != NULL) {
230  ocs_textbuf_free(ocs, &ocs->ddump_saved);
231  ocs_ramlog_free(ocs, ocs->ramlog);
232  ocs_devices[ocs->instance_index] = NULL;
234 #if defined(ENABLE_LOCK_DEBUG)
235  {
236  ocs_os_t *os = &ocs->ocs_os;
237  ocs_lock_t *l;
238  uint32_t count = 0;
239  ocs_list_foreach(&os->locklist, l) {
240  ocs_log_test(os, "%s not freed\n", l->name);
241  count++;
242  }
243  if (count == 0) {
244  ocs_log_debug(ocs, "all lock objects freed\n");
245  }
246  }
247 #endif
248  ocs_free(ocs, ocs, sizeof(*ocs));
249  }
250 }
251 
252 /**
253  * @brief return the number of interrupts required per HBA
254  *
255  * @param ocs pointer to ocs structure
256  *
257  * @return the number of interrupts or negative value on error.
258  */
260 {
261  /* So we set the port type properly in ocs_hal_setup */
262  ocs->enable_ini = initiator;
263  ocs->enable_tgt = target;
264 
265  return ocs_iscsi_interrupts_required((ocs_os_handle_t)ocs, &ocs->hal);
266 }
267 
268 /**
269  * @brief Initialize resources when pci devices attach
270  *
271  * @param ocs pointer to ocs structure
272  *
273  * @return 0 for success, a negative error code value for failure.
274  */
275 
276 int32_t
277 ocs_device_attach(ocs_t *ocs)
278 {
279  uint32_t rc = 0;
280 
281  if (ocs->drv_ocs.attached) {
282  ocs_log_test(ocs, "Device is already attached\n");
283  rc = -1;
284  } else {
285  ocs_snprintf(ocs->display_name, sizeof(ocs->display_name), "[%s%d] ", "i", ocs->instance_index);
286 
287  /* copy the module paramaters to ocs */
288  ocs->enable_ini = initiator;
289  ocs->enable_tgt = target;
290  ocs->num_scsi_ios = num_scsi_ios;
291  ocs->model = ocs_pci_model(ocs->pci_vendor, ocs->pci_device);
292  ocs->driver_version = DRV_VERSION;
293 
294 #if defined(OCS_INCLUDE_RAMD)
295  ocs->num_tgts = num_tgts;
296  ocs->global_ramdisc = global_ramdisc;
297 #else
298  /* num_tgts is used in a lot of code. Set to 1 for now */
299  ocs->num_tgts = 1;
300 #endif
301 
302  ocs_strcpy(ocs->local_ip, local_ip);
303  ocs_strcpy(ocs->local_subnet, local_subnet);
304  ocs_strcpy(ocs->iqn_prefix, iqn_prefix);
305  ocs_strcpy(ocs->iqn_suffix,
306  (iqn_suffix[ocs->instance_index] ?
307  iqn_suffix[ocs->instance_index] :
309  ocs_strcpy(ocs->gateway, gateway);
310  ocs->tcp_window_size = tcp_window_size;
311  ocs->tcp_window_scale = tcp_window_scale;
312  ocs->num_scsi_ios = num_scsi_ios;
313  ocs->ctrlmask = ctrlmask;
314  ocs->num_cxns = num_cxns;
315  ocs->hal_war_version = hal_war_version;
316  ocs->max_cxns_per_session = OCS_ISCSI_MAX_CXNS_PER_SESSION;
317 
318  ocs->enable_sgl_chaining = (enable_sgl_chaining == 0 ? FALSE : TRUE);
319  ocs->enable_immediate_data = (enable_immediate_data == 0 ? FALSE : TRUE);
320  ocs->enable_hdr_digest = (enable_hdr_digest == 0 ? FALSE : TRUE);
321  ocs->enable_data_digest = (enable_data_digest == 0 ? FALSE : TRUE);
322  ocs->enable_jumbo_frame = (enable_jumbo_frame == 0 ? FALSE : TRUE);
323  ocs->require_chap = FALSE;
324 
325  /* non-zero target IO timer not supported for iSCSI */
326  ocs->target_io_timer_sec = 0;
327 
328  if (max_sge_size < 1024 &&
329  max_sge_size > 65536) {
330  ocs_log_test(ocs, "Ignoring invalid max_sge_size\n");
331  } else {
332  ocs->max_sge_size = max_sge_size;
333  }
334  ocs->post_sgl_config = post_sgl_config;
335 
336  rc = ocs_iscsi_initialize(ocs, &ocs->iscsi, &ocs->hal, ocs->instance_index);
337  if (rc == 0) {
338  rc = ocs_start_event_processing(&ocs->ocs_os);
339  }
340  }
341  ocs->desc = ocs->hal.sli.config.modeldesc;
342  ocs_log_info(ocs, "adapter model description: %s\n", ocs->hal.sli.config.modeldesc);
343  if (rc == 0) {
344  ocs->drv_ocs.attached = TRUE;
345  } else {
346  ocs_teardown_msix((ocs_os_t *)ocs);
347  }
348 
349  return rc;
350 }
351 
352 /**
353  * @brief interrupt handler
354  *
355  * Interrupt handler
356  *
357  * @param ocs pointer to ocs structure
358  * @param vector Zero-based interrupt vector number.
359  *
360  * @return none
361  */
362 
363 static void
364 ocs_device_interrupt_handler(ocs_t *ocs, uint32_t vector)
365 {
366  ocs_hal_process(&ocs->hal, vector, ocs->max_isr_time_msec);
367 }
368 
369 /**
370  * @brief free resources when pci device detach
371  *
372  * @param ocs pointer to ocs structure
373  *
374  * @return 0 for success, a negative error code value for failure.
375  */
376 
377 int32_t
378 ocs_device_detach(ocs_t *ocs)
379 {
380  if (ocs != NULL) {
381  if (!ocs->drv_ocs.attached) {
382  ocs_log_test(ocs, "Device is not attached\n");
383  return -1;
384  }
385 
386  /* Check and invalidate active connections before disabling interrupts */
387  ocs_iscsi_cxn_req_invalidate(&ocs->iscsi);
388 
389  ocs_intr_disable(ocs);
390 
391  if (ocs_iscsi_teardown(&ocs->iscsi)) {
392  ocs_log_err(ocs, "ocs_iscsi_teardown failed\n");
393  }
394 
395  ocs_stop_event_processing(&ocs->ocs_os);
396 
397  ocs_xport_free(ocs->xport);
398  ocs->xport = NULL;
399 
400  ocs->drv_ocs.attached = FALSE;
401  }
402 
403  return 0;
404 }
405 
406 /**
407  * @brief get driver wide property value
408  *
409  * Return valued driver wide property. All property values using this interface
410  * are returned as null terminated text.
411  *
412  * @param prop_name property name
413  * @param buffer pointer to buffer
414  * @param buffer_len length of buffer in bytes
415  *
416  * @return returns 0 for success, a negative error code value for failure.
417  */
418 
419 int32_t
420 ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
421 {
422  if (ocs_strcmp(prop_name, "initiator") == 0) {
423  ocs_snprintf(buffer, buffer_len, "%d", initiator);
424  } else if (ocs_strcmp(prop_name, "target") == 0) {
425  ocs_snprintf(buffer, buffer_len, "%d", target);
426 #if defined(OCS_INCLUDE_RAMD)
427  } else if (ocs_strcmp(prop_name, "global_ramdisc") == 0) {
428  ocs_snprintf(buffer, buffer_len, "%d", global_ramdisc);
429  } else if (ocs_strcmp(prop_name, "ramdisc_size") == 0) {
430  ocs_strncpy(buffer, ramdisc_size, buffer_len);
431  } else if (ocs_strcmp(prop_name, "ramdisc_blocksize") == 0) {
432  ocs_snprintf(buffer, buffer_len, "%d", ramdisc_blocksize);
433  } else if (ocs_strcmp(prop_name, "num_luns") == 0) {
434  ocs_snprintf(buffer, buffer_len, "%d", num_luns);
435  } else if (ocs_strcmp(prop_name, "p_type") == 0) {
436  ocs_snprintf(buffer, buffer_len, "%d", p_type);
437  } else if (ocs_strcmp(prop_name, "stub_res6_rel6") == 0) {
438  ocs_snprintf(buffer, buffer_len, "%d", stub_res6_rel6);
439  } else if (strcmp(prop_name, "ramd_threading") == 0) {
440  ocs_snprintf(buffer, buffer_len, "%d", ramd_threading);
441  } else if (strcmp(prop_name, "thread_cmds") == 0) {
442  ocs_snprintf(buffer, buffer_len, "%d", thread_cmds);
443  } else if (strcmp(prop_name, "external_dif") == 0) {
444  ocs_strncpy(buffer, external_dif, buffer_len);
445  } else if (ocs_strcmp(prop_name, "num_tgts") == 0) {
446  ocs_snprintf(buffer, buffer_len, "%d", num_tgts);
447 #endif
448  } else if (ocs_strcmp(prop_name, "dif_separate") == 0) {
449  /* iSCSI only supports DIF separate */
450  ocs_snprintf(buffer, buffer_len, "%d", 1);
451  } else {
452  ocs_log_test(NULL, "Error: unknown property %s\n", prop_name);
453  ocs_snprintf(buffer, buffer_len, "%s", "");
454  return -1;
455  }
456  return 0;
457 }
458 
459 /**
460  * @brief return OCS instance display name
461  *
462  * returns const char string of OCS instance display name
463  *
464  * @param os pointer to OS (ocs_t) object
465  *
466  * @return return display name
467  */
468 
469 const char *ocs_display_name(void *os)
470 {
471  ocs_t *ocs = os;
472  ocs_assert(ocs, "[?]");
473  return ocs->display_name;
474 }
475 
476 void ocs_mgmt_driver_list(ocs_textbuf_t *textbuf, void *object)
477 {
478 
479  ocs_mgmt_start_unnumbered_section(textbuf, "driver");
480 
481  /* Readonly values */
482  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ctrlmask");
483  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_cxns");
484  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ddump_saved_size");
485  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_data_digest");
486  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_hdr_digest");
487  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_immediate_data");
488  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_jumbo_frame");
489  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "enable_sgl_chaining");
490  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "gateway");
491  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hal_war_version");
492  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "hw_cmpl_context");
493  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "initiator");
494  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "local_ip");
495  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "local_subnet");
496  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "logdest");
497  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "max_sge_size");
498  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_luns");
499  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_scsi_ios");
500  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "post_sgl_config");
501  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "global_ramdisc");
502  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ramdisc_blocksize");
503  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ramdisc_size");
504  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "ramlog_size");
505  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "target");
506  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "tcp_window_scale");
507  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "tcp_window_size");
508  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_RD, "num_tgts");
509 
510  /* Actions */
511  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "clear_ramlog");
512  ocs_mgmt_emit_property_name(textbuf, MGMT_MODE_EX, "read_block");
513 
514  ocs_mgmt_end_unnumbered_section(textbuf, "driver");
515 
516  return;
517 }
518 
519 int ocs_mgmt_driver_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *object)
520 {
521  char qualifier[80];
522  int retval = -1;
523 
524  ocs_mgmt_start_unnumbered_section(textbuf, "driver");
525 
526  ocs_snprintf(qualifier, sizeof(qualifier), "%s/driver", parent);
527 
528  /* If it doesn't start with my qualifier I don't know what to do with it */
529  if (ocs_strncmp(name, qualifier, strlen(qualifier)) == 0) {
530  char *unqualified_name = name + strlen(qualifier) +1;
531 
532  /* See if it's a value I can supply */
533  if (ocs_strcmp(unqualified_name, "ctrlmask") == 0) {
534  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ctrlmask", "0x%x", ctrlmask);
535  retval = 0;
536  } else if (ocs_strcmp(unqualified_name, "num_cxns") == 0) {
537  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_cxns", "%d", num_cxns);
538  retval = 0;
539  } else if (ocs_strcmp(unqualified_name, "ddump_saved_size") == 0) {
540  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ddump_saved_size", "%d", ddump_saved_size);
541  retval = 0;
542  } else if (ocs_strcmp(unqualified_name, "enable_data_digest") == 0) {
543  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_data_digest", enable_data_digest);
544  retval = 0;
545  } else if (ocs_strcmp(unqualified_name, "enable_hdr_digest") == 0) {
546  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_hdr_digest", enable_hdr_digest);
547  retval = 0;
548  } else if (ocs_strcmp(unqualified_name, "enable_immediate_data") == 0) {
549  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_immediate_data", enable_immediate_data);
550  retval = 0;
551  } else if (ocs_strcmp(unqualified_name, "enable_jumbo_frame") == 0) {
552  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_jumbo_frame", enable_jumbo_frame);
553  retval = 0;
554  } else if (ocs_strcmp(unqualified_name, "enable_sgl_chaining") == 0) {
555  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_sgl_chaining", enable_sgl_chaining);
556  retval = 0;
557  } else if (ocs_strcmp(unqualified_name, "gateway") == 0) {
558  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "gateway", gateway);
559  retval = 0;
560  } else if (ocs_strcmp(unqualified_name, "hal_war_version") == 0) {
561  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "hal_war_version", hal_war_version);
562  retval = 0;
563  } else if (ocs_strcmp(unqualified_name, "hw_cmpl_context") == 0) {
564  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_cmpl_context", "%d", hw_cmpl_context);
565  retval = 0;
566  } else if (ocs_strcmp(unqualified_name, "initiator") == 0) {
567  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "initiator", initiator);
568  retval = 0;
569  } else if (ocs_strcmp(unqualified_name, "local_ip") == 0) {
570  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "local_ip", local_ip);
571  retval = 0;
572  } else if (ocs_strcmp(unqualified_name, "local_subnet") == 0) {
573  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "local_subnet", local_subnet);
574  retval = 0;
575  } else if (ocs_strcmp(unqualified_name, "logdest") == 0) {
576  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "logdest", "0x%x", logdest);
577  retval = 0;
578  } else if (ocs_strcmp(unqualified_name, "max_sge_size") == 0) {
579  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "max_sge_size", "%d", max_sge_size);
580  retval = 0;
581  } else if (ocs_strcmp(unqualified_name, "num_scsi_ios") == 0) {
582  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_scsi_ios", "%d", num_scsi_ios);
583  retval = 0;
584  } else if (ocs_strcmp(unqualified_name, "post_sgl_config") == 0) {
585  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "post_sgl_config", "%d", post_sgl_config);
586  retval = 0;
587 #if defined(OCS_INCLUDE_RAMD)
588  } else if (ocs_strcmp(unqualified_name, "num_luns") == 0) {
589  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_luns", "%d", num_luns);
590  retval = 0;
591  } else if (ocs_strcmp(unqualified_name, "global_ramdisc") == 0) {
592  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "global_ramdisc", "%d", global_ramdisc);
593  retval = 0;
594  } else if (ocs_strcmp(unqualified_name, "ramdisc_blocksize") == 0) {
595  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramdisc_blocksize", "%d", ramdisc_blocksize);
596  retval = 0;
597  } else if (ocs_strcmp(unqualified_name, "ramdisc_size") == 0) {
598  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ramdisc_size", ramdisc_size);
599  retval = 0;
600  } else if (ocs_strcmp(unqualified_name, "num_tgts") == 0) {
601  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_tgts", "%d", num_tgts);
602  retval = 0;
603 #endif
604  } else if (ocs_strcmp(unqualified_name, "ramlog_size") == 0) {
605  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramlog_size", "%d", ramlog_size);
606  retval = 0;
607  } else if (ocs_strcmp(unqualified_name, "target") == 0) {
608  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "target", target);
609  retval = 0;
610  } else if (ocs_strcmp(unqualified_name, "tcp_window_scale") == 0) {
611  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tcp_window_scale", "%d", tcp_window_scale);
612  retval = 0;
613  } else if (ocs_strcmp(unqualified_name, "tcp_window_size") == 0) {
614  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tcp_window_size", "%d", tcp_window_size);
615  retval = 0;
616  }
617  }
618 
619  ocs_mgmt_end_unnumbered_section(textbuf, "driver");
620 
621  return retval;
622 }
623 
624 void ocs_mgmt_driver_get_all(ocs_textbuf_t *textbuf, void *object)
625 {
626  ocs_mgmt_start_unnumbered_section(textbuf, "driver");
627 
628  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ctrlmask", "0x%x", ctrlmask);
629  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_cxns", "%d", num_cxns);
630  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ddump_saved_size", "%d", ddump_saved_size);
631  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_data_digest", enable_data_digest);
632  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_hdr_digest", enable_hdr_digest);
633  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_immediate_data", enable_immediate_data);
634  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_jumbo_frame", enable_jumbo_frame);
635  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "enable_sgl_chaining", enable_sgl_chaining);
636  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "gateway", gateway);
637  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "hal_war_version", hal_war_version);
638  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "hw_cmpl_context", "%d", hw_cmpl_context);
639  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "initiator", initiator);
640  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "local_ip", local_ip);
641  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "local_subnet", local_subnet);
642  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "logdest", "0x%x", logdest);
643  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "max_sge_size", "%d", max_sge_size);
644  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_scsi_ios", "%d", num_scsi_ios);
645  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "post_sgl_config", "%d", post_sgl_config);
646 #if defined(OCS_INCLUDE_RAMD)
647  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_luns", "%d", num_luns);
648  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "global_ramdisc", "%d", global_ramdisc);
649  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramdisc_blocksize", "%d", ramdisc_blocksize);
650  ocs_mgmt_emit_string(textbuf, MGMT_MODE_RD, "ramdisc_size", ramdisc_size);
651  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "num_tgts", "%d", num_tgts);
652 #endif
653  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "ramlog_size", "%d", ramlog_size);
654  ocs_mgmt_emit_boolean(textbuf, MGMT_MODE_RD, "target", target);
655  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tcp_window_scale", "%d", tcp_window_scale);
656  ocs_mgmt_emit_int(textbuf, MGMT_MODE_RD, "tcp_window_size", "%d", tcp_window_size);
657 
658  ocs_mgmt_end_unnumbered_section(textbuf, "driver");
659 }
660 
661 
662 int ocs_mgmt_driver_exec(char *parent, char *action_name, void *arg_in,
663  uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length, void *object)
664 {
665  char qualifier[80];
666  int retval = -1;
667  ocs_t *ocs = (ocs_t *)object;
668 
669  ocs_snprintf(qualifier, sizeof(qualifier), "%s/driver", parent);
670 
671  /* If it doesn't start with my qualifier I don't know what to do with it */
672  if (ocs_strncmp(action_name, qualifier, strlen(qualifier)) == 0) {
673  char *unqualified_name = action_name + strlen(qualifier) +1;
674 
675  if (ocs_strcmp(unqualified_name, "clear_ramlog") == 0) {
676  char local_arg_in[128];
677  int clear_start_of_day = 0;
678  int clear_recent = 0;
679  if (arg_in) {
680  if (ocs_copy_from_user(local_arg_in, arg_in,
681  MIN(arg_in_length, sizeof(local_arg_in)-1))) {
682  ocs_log_test(ocs, "Error: copy arg_in from user failed\n");
683  return -1;
684  }
685 
686  local_arg_in[sizeof(local_arg_in)-1] = 0;
687  if (ocs_strcmp(local_arg_in, "recent") == 0) {
688  clear_recent = 1;
689  } else if (ocs_strcmp(local_arg_in, "start_of_day") == 0) {
690  clear_start_of_day = 1;
691  } else if (ocs_strcmp(local_arg_in, "all") == 0) {
692  clear_recent = 1;
693  clear_start_of_day = 1;
694  }
695  } else {
696  clear_recent = 1;
697  clear_start_of_day = 1;
698  }
699 
700  ocs_log_debug(ocs, "Clear ramlog:%s%s\n", clear_start_of_day ? " start_of_day" : "",
701  clear_recent ? " recent" : "");
702 
703  ocs_ramlog_clear(ocs, ocs->ramlog, clear_start_of_day, clear_recent);
704  retval = 0;
705  }
706 #if defined(OCS_INCLUDE_RAMD)
707  if (ocs_strcmp(unqualified_name, "read_block") == 0) {
708  retval = ocs_mgmt_read_block(ocs, unqualified_name, arg_in, arg_in_length,
709  arg_out, arg_out_length);
710  }
711 #endif
712  }
713 
714  return retval;
715 }
716 
717 #if defined(OCS_INCLUDE_RAMD)
718 static int32_t
719 ocs_mgmt_read_block(ocs_t *ocs, char *name, void *arg_in, uint32_t arg_in_length, void *arg_out, uint32_t arg_out_length)
720 {
721  uint32_t tgt;
722  uint32_t lun;
723  uint32_t lba;
724  char input_buffer[80];
725  ocs_ramdisc_t *ramdisc;
726  uint8_t *block;
727  uint32_t length;
728 
729  if ((arg_in == NULL) ||
730  (arg_in_length == 0) ||
731  (arg_out == NULL) ||
732  (arg_out_length == 0)) {
733  return -1;
734  }
735 
736  if (arg_in_length > sizeof(input_buffer)) {
737  arg_in_length = sizeof(input_buffer);
738  }
739 
740  if (ocs_copy_from_user(input_buffer, arg_in, arg_in_length)) {
741  ocs_log_test(ocs, "Failed to copy addr from user\n");
742  return -EFAULT;
743  }
744 
745  if (ocs_sscanf(input_buffer, "%d:%d:%d", &tgt, &lun, &lba) != 3) {
746  return -EFAULT;
747  }
748 
749  ramdisc = ocs_ramd_lookup_by_tgt(ocs, tgt, lun);
750  if (ramdisc == NULL) {
751  return -EFAULT;
752  }
753 
754  block = ocs_ramdisc_lba_address(ramdisc, lba);
755 
756  length = arg_out_length;
757 
758  if (ocs_copy_to_user(arg_out, block, length)) {
759  ocs_log_test(ocs, "Failed to copy buffer to user\n");
760  return -EFAULT;
761  }
762 
763 
764  return 0;
765 }
766 #endif
767 
int32_t ocs_device_detach(ocs_t *ocs)
Remove the PCI device instance.
Definition: ocs_driver.c:334
const char * ocs_display_name(void *os)
Definition: ocs_driver.c:385
int32_t ocs_scsi_tgt_driver_init(void)
Driver-wide initialization for the target-server.
Definition: ocs_ramd.c:354
int32_t ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len)
Definition: ocs_driver.c:357
void ocs_device_shutdown(void)
Perform driver-wide shut down actions.
Definition: ocs_driver.c:125
uint8_t * ocs_ramdisc_lba_address(ocs_ramdisc_t *ramdisc, uint64_t lba)
Return the address of a ramdisc logical block.
Definition: ocs_ramdisc.c:577
int32_t ocs_scsi_ini_driver_init(int32_t initiator)
Initialize initiator client.
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.
#define DRV_VERSION
Definition: ocs.h:45
int32_t ocs_scsi_tgt_driver_exit(void)
Driver-wide clean-up for the target-server.
Definition: ocs_ramd.c:401
#define OCS_IQN_SUFFIX_DEFAULT
Definition: ocs_common.h:241
static void ocs_device_lock_init(ocs_t *ocs)
Definition: ocs_drv_fc.h:187
ocs_t * ocs_devices[MAX_OCS_DEVICES]
Definition: ocs_driver.c:40
void * ocs_device_alloc(uint32_t nid)
Instantiate the PCI device.
Definition: ocs_driver.c:181
#define MGMT_MODE_EX
Definition: ocs_mgmt.h:49
void ocs_device_free(ocs_t *ocs)
Definition: ocs_driver.c:227
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
void ocs_iscsi_cxn_req_invalidate(ocs_iscsi_t *iscsi)
Definition: ocs_iscsi.c:4456
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)
Definition: ocs_driver.c:553
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_device_interrupts_required(ocs_t *ocs)
Returns the number of interrupts required per HBA.
Definition: ocs_driver.c:261
ramdisc instance structure
Definition: ocs_ramdisc.h:88
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.
int32_t ocs_device_attach(ocs_t *ocs)
Definition: ocs_driver.c:271
void ocs_ramlog_free(ocs_t *ocs, ocs_ramlog_t *ramlog)
Free a ramlog buffer.
Definition: ocs_ramlog.c:116
void ocs_device_shutdown_complete(void)
Perform driver-wide shutdown complete actions.
Definition: ocs_driver.c:568
#define ocs_list_init(head, type, link)
Definition: ocs_list.h:113
int32_t ocs_start_event_processing(ocs_os_t *ocs_os)
int32_t ocs_hal_process(ocs_hal_t *hal, uint32_t vector, uint32_t max_isr_time_msec)
Process events associated with the interrupt vector.
Definition: ocs_hal.c:2971
void ocs_mgmt_end_unnumbered_section(ocs_textbuf_t *textbuf, const char *name)
Generate the end of a section in a management XML document.
ocs_ramdisc_t * ocs_ramd_lookup_by_tgt(ocs_t *ocs, uint32_t tgt, uint32_t lun)
Given an TGT number and a LUN number, return the corresponding ramdisc.
Definition: ocs_ramd.c:519
void ocs_mgmt_driver_list(ocs_textbuf_t *textbuf, void *driver)
Definition: ocs_driver.c:392
PARAM_LIST int32_t ocs_device_init(void)
Perform driver-wide initialization.
Definition: ocs_driver.c:74
ocs_mgmt_get_list_handler get_list_handler
Definition: ocs_mgmt.h:83
int32_t ocs_iscsi_initialize(ocs_os_handle_t os, ocs_iscsi_t *iscsi, ocs_hal_t *hal, uint32_t device_instance)
Initialize the iSCSI device by setting up the chip.
Definition: ocs_iscsi.c:1505
int32_t ocs_iscsi_teardown(ocs_iscsi_t *iscsi)
Shut down the device.
Definition: ocs_iscsi.c:1921
#define MGMT_MODE_RD
Definition: ocs_mgmt.h:47
int32_t ocs_scsi_ini_driver_exit(int32_t initiator)
initiator client exit
#define OCS_RAMLOG_DEFAULT_BUFFERS
Definition: ocs_ramlog.h:46
int32_t ocs_iscsi_interrupts_required(ocs_os_handle_t os, ocs_hal_t *hal)
Returns the number of interrupts needed for this adapter.
Definition: ocs_iscsi.c:1459
void ocs_stop_event_processing(ocs_os_t *ocs_os)
void ocs_mgmt_driver_get_all(ocs_textbuf_t *textbuf, void *driver)
Definition: ocs_driver.c:516
void ocs_xport_free(ocs_xport_t *xport)
free a transport object
Definition: ocs_xport.c:471
#define ocs_assert(cond,...)
Definition: ocs_debug.h:163
int logdest
Definition: ocs_lnx.c:24
int32_t ocs_device_init_complete(void)
Perform device initialization complete.
Definition: ocs_driver.c:110
int32_t ocs_textbuf_alloc(ocs_t *ocs, ocs_textbuf_t *textbuf, uint32_t length)
Definition: ocs_textbuf.c:105
static void ocs_device_interrupt_handler(ocs_t *ocs, uint32_t vector)
interrupt handler
Definition: ocs_driver.c:364
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
static int32_t ocs_mgmt_read_block(ocs_t *ocs, char *, void *, uint32_t, void *, uint32_t)
Definition: ocs_ramd.c:7081
static ocs_mgmt_functions_t driver_mgmt_functions
Definition: ocs_driver.c:57
#define OCS_ISCSI_MAX_CXNS_PER_SESSION
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
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.
int ocs_mgmt_driver_get(ocs_textbuf_t *textbuf, char *parent, char *name, void *driver)
Definition: ocs_driver.c:425