Emulex Logo
OneCoreā„¢ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ocs_debug.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 /**
34  * @file
35  * Provides general purpose debug facilities
36  */
37 /*!
38 @defgroup debug Debug Support Functions
39 */
40 
41 #include "ocs.h"
42 #include "sli4_iscsi.h"
43 
44 #define OCS_DEBUG_ENABLE(x) (x ? ~0 : 0)
45 
46 // change '0' to '1' to enable debug feature
47 #define OCS_DEBUG_MASK \
48  (OCS_DEBUG_ENABLE(1) & OCS_DEBUG_ALWAYS) | \
49  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_MQ_DUMP) | \
50  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_CQ_DUMP) | \
51  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_WQ_DUMP) | \
52  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_IO_TRACE) | \
53  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_SM_TRACE) | \
54  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_SCSI_TGT_TRACE) | \
55  (OCS_DEBUG_ENABLE(0) & OCS_DEBUG_ENABLE_ISNS_LOG)
56 
57 static uint32_t ocs_debug_mask = OCS_DEBUG_MASK;
58 
59 #if defined(OCS_DEBUG_QUEUE_HISTORY)
60 /**
61  * @brief WQE command mask lookup
62  */
63 typedef struct ocs_q_hist_wqe_mask_s {
64  uint8_t type;
65  uint32_t mask;
66 } ocs_q_hist_wqe_mask_t;
67 
68 /**
69  * @brief CQE mask lookup
70  */
71 typedef struct ocs_q_hist_cqe_mask_s {
72  sli4_qentry_e ctype;
73  uint32_t :Q_HIST_MASK_LEN,
74  type:Q_HIST_TYPE_LEN;
75  uint32_t mask;
76 } ocs_q_hist_cqe_mask_t;
77 
78 #endif
79 
80 /**
81  * @ingroup debug
82  * @brief enable debug options
83  *
84  * Enables debug options by or-ing in <b>mask</b> into the currently enabled
85  * debug mask.
86  *
87  * @param mask mask bits to enable
88  *
89  * @return none
90  */
91 void ocs_debug_enable(uint32_t mask) {
92  ocs_debug_mask |= mask;
93 }
94 
95 /**
96  * @ingroup debug
97  * @brief disable debug options
98  *
99  * Disables debug options by clearing bits in <b>mask</b> into the currently enabled
100  * debug mask.
101  *
102  * @param mask mask bits to enable
103  *
104  * @return none
105  */
106 void ocs_debug_disable(uint32_t mask) {
107  ocs_debug_mask &= ~mask;
108 }
109 
110 /**
111  * @ingroup debug
112  * @brief return true if debug bits are enabled
113  *
114  * Returns true if the request debug bits are set.
115  *
116  * @param mask debug bit mask
117  *
118  * @return true if corresponding bits are set
119  *
120  * @note Passing in a mask value of zero always returns true
121  */
122 int ocs_debug_is_enabled(uint32_t mask) {
123  return (ocs_debug_mask & mask) == mask;
124 }
125 
126 
127 /**
128  * @ingroup debug
129  * @brief Dump 32 bit hex/ascii data
130  *
131  * Dumps using ocs_log a buffer of data as 32 bit hex and ascii
132  *
133  * @param mask debug enable bits
134  * @param os os handle
135  * @param label text label for the display (may be NULL)
136  * @param buf pointer to data buffer
137  * @param buf_length length of data buffer
138  *
139  * @return none
140  *
141  */
142 void
143 ocs_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length) {
144  const uint32_t columns = 8;
145  uint32_t word_count = buf_length / sizeof(uint32_t);
146  uint32_t *wbuf = buf;
147  uint32_t offset = 0;
148  uint32_t i;
149  uint32_t n;
150  char str[96];
151  char temp[16];
152 
153  if (!ocs_debug_is_enabled(mask)) {
154  return;
155  }
156 
157  if (label) {
158  ocs_log_debug(os, "%s\n", label);
159  }
160 
161  while (word_count > 0) {
162  ocs_snprintf(str, ARRAY_SIZE(str), "%08X: ", offset);
163  n = (word_count > columns ? columns : word_count);
164  for (i = 0; i < n; i ++) {
165  ocs_snprintf(temp, ARRAY_SIZE(temp), " %08X", wbuf[i]);
166  strcat(str, temp);
167  }
168 
169  ocs_log_debug(os, "%s\n", str);
170  wbuf += n;
171  word_count -= n;
172  offset += n * sizeof(uint32_t);
173  }
174 }
175 
176 /**
177  * @ingroup debug
178  * @brief Dump 32 bit hex/ascii data after first swapping
179  * endianess
180  *
181  * Copies data in buf to a new buffer using ocs_be32toh to swap
182  * endianess, then dumps the buffer by calling ocs_dumpt32.
183  *
184  * @param mask debug enable bits
185  * @param os os handle
186  * @param label text label for the display (may be NULL)
187  * @param buf pointer to data buffer
188  * @param buf_length length of data buffer
189  *
190  * @return none
191  *
192  */
193 #define MAX_BUF_BYTES 1024
194 #define MAX_BUF_WORDS (MAX_BUF_BYTES/sizeof(uint32_t))
195 
196 void ocs_swap_and_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length) {
197  uint32_t swapped_buf[MAX_BUF_WORDS];
198  uint32_t *src;
199  uint32_t *dst;
200  uint32_t i;
201 
202  if (buf_length > MAX_BUF_BYTES) {
203  buf_length = MAX_BUF_BYTES;
204  }
205 
206  src = buf;
207  dst = swapped_buf;
208  for (i=0; i<(buf_length / sizeof(uint32_t)); i++) {
209  *dst = ocs_be32toh(*src);
210  ++dst;
211  ++src;
212  }
213 
214  ocs_dump32(mask, os, label, swapped_buf, buf_length);
215 }
216 
217 
218 #if !defined(OCS_EXPORT)
219 #define OCS_EXPORT(...)
220 #endif
221 
222 #if defined(OCS_DEBUG_QUEUE_HISTORY)
223 
224 /* each bit corresponds to word to capture */
225 #define OCS_Q_HIST_WQE_WORD_MASK_DEFAULT (BIT(6) | BIT(7) | BIT(9) | BIT(11))
226 #define OCS_Q_HIST_IWRITE_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(6) | BIT(7) | BIT(10) | BIT(11))
227 #define OCS_Q_HIST_ITMF_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(7))
228 #define OCS_Q_HIST_INOP_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(7))
229 #define OCS_Q_HIST_IREAD_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(6) | BIT(7) | BIT(10) | BIT(11))
230 #define OCS_Q_HIST_CXTUPD_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(8) | BIT(11))
231 #define OCS_Q_HIST_TSTS_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(6) | BIT(7) | BIT(10) | BIT(11))
232 #define OCS_Q_HIST_TDATAIN_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(6) | BIT(10) | BIT(11))
233 #define OCS_Q_HIST_TSOS_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(11))
234 #define OCS_Q_HIST_DMCMD_WQE_WORD_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(7) | BIT(11))
235 #define OCS_Q_HIST_ISOL_CQE_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
236 #define OCS_Q_HIST_TSOL_CQE_MASK (BIT(1) | BIT(2) | BIT(3))
237 #define OCS_Q_HIST_DDIGEST_CQE_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
238 #define OCS_Q_HIST_CNXINV_CQE_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
239 #define OCS_Q_HIST_CMDINV_CQE_MASK (BIT(2) | BIT(3))
240 #define OCS_Q_HIST_DPDU_CQE_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
241 #define OCS_Q_HIST_DMSG_CQE_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
242 #define OCS_Q_HIST_ASYNC_CQE_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
243 #define OCS_Q_HIST_MQ_CQE_MASK (BIT(0) | BIT(1) | BIT(2))
244 #define OCS_Q_HIST_TX_DIFF_CQE_MASK (BIT(0) | BIT(2) | BIT(3))
245 
246 /* if set, will provide extra queue information in each entry */
247 #define OCS_Q_HIST_ENABLE_Q_INFO 1
248 uint8_t ocs_queue_history_q_info_enabled(void)
249 {
250  return OCS_Q_HIST_ENABLE_Q_INFO;
251 }
252 
253 /* if set, will provide timestamps in each entry */
254 #define OCS_Q_HIST_ENABLE_TIMESTAMPS 0
255 uint8_t ocs_queue_history_timestamp_enabled(void)
256 {
257  return OCS_Q_HIST_ENABLE_TIMESTAMPS;
258 }
259 
260 /* Add WQEs and masks to override default WQE mask */
261 ocs_q_hist_wqe_mask_t ocs_q_hist_wqe_masks[] = {
262  /* WQE command Word mask */
263  {SLI4_WQE_INI_WRITE, OCS_Q_HIST_IWRITE_WQE_WORD_MASK},
264  {SLI4_WQE_INI_TMF, OCS_Q_HIST_ITMF_WQE_WORD_MASK},
265  {SLI4_WQE_INI_NOP, OCS_Q_HIST_INOP_WQE_WORD_MASK},
266  {SLI4_WQE_INI_READ, OCS_Q_HIST_IREAD_WQE_WORD_MASK},
267  {SLI4_WQE_CONTEXT_UPDATE, OCS_Q_HIST_CXTUPD_WQE_WORD_MASK},
268  {SLI4_WQE_TGT_STS, OCS_Q_HIST_TSTS_WQE_WORD_MASK},
269  {SLI4_WQE_TGT_DATAIN, OCS_Q_HIST_TDATAIN_WQE_WORD_MASK},
270  {SLI4_WQE_TGT_SOS, OCS_Q_HIST_TSOS_WQE_WORD_MASK},
271  {SLI4_WQE_UNASSISTED, OCS_Q_HIST_DMCMD_WQE_WORD_MASK},
272 };
273 
274 /* CQE masks */
275 ocs_q_hist_cqe_mask_t ocs_q_hist_cqe_masks[] = {
276  /* CQE type Q_hist_type mask */
277  {SLI_CQENTRY_RQ, OCS_Q_HIST_TYPE_CQE_RQ, OCS_Q_HIST_DPDU_CQE_MASK},
278  {SLI_CQENTRY_TCP_ACK, OCS_Q_HIST_TYPE_CQE_TCP_ACK, OCS_Q_HIST_DMSG_CQE_MASK},
279  {SLI_CQENTRY_INI_IO, OCS_Q_HIST_TYPE_CQE_INI_IO, OCS_Q_HIST_ISOL_CQE_MASK},
280  {SLI_CQENTRY_TGT_IO, OCS_Q_HIST_TYPE_CQE_TGT_IO, OCS_Q_HIST_TSOL_CQE_MASK},
281  {SLI_CQENTRY_TGT_CMD_INVALID, OCS_Q_HIST_TYPE_CQE_CMDINV, OCS_Q_HIST_CMDINV_CQE_MASK},
282  {SLI_CQENTRY_ASYNC, OCS_Q_HIST_TYPE_CQE_ASYNC, OCS_Q_HIST_ASYNC_CQE_MASK},
283  {SLI_CQENTRY_MQ, OCS_Q_HIST_TYPE_CQE_MQ, OCS_Q_HIST_MQ_CQE_MASK},
284  {SLI_CQENTRY_CNX_INVALID, OCS_Q_HIST_TYPE_CQE_CNXINV, OCS_Q_HIST_CNXINV_CQE_MASK},
285  {SLI_CQENTRY_TGT_DATA_DIGEST, OCS_Q_HIST_TYPE_CQE_T_DDIGEST, OCS_Q_HIST_DDIGEST_CQE_MASK},
286  {SLI_CQENTRY_TX_DIF_ERROR, OCS_Q_HIST_TYPE_CQE_TX_DIF, OCS_Q_HIST_TX_DIFF_CQE_MASK},
287 };
288 
289 static uint32_t ocs_q_hist_get_wqe_mask(sli4_skh_wqe_unassisted_t *wqe)
290 {
291  uint32_t i;
292  for (i = 0; i < ARRAY_SIZE(ocs_q_hist_wqe_masks); i++) {
293  if (ocs_q_hist_wqe_masks[i].type == wqe->type) {
294  return ocs_q_hist_wqe_masks[i].mask;
295  }
296  }
297  /* return default WQE mask */
298  return OCS_Q_HIST_WQE_WORD_MASK_DEFAULT;
299 }
300 
301 /**
302  * @ingroup debug
303  * @brief Initialize resources for queue history
304  *
305  * @param os os handle
306  * @param q_hist Pointer to the queue history object.
307  *
308  * @return none
309  */
310 void
311 ocs_queue_history_init(ocs_t *ocs, ocs_hal_q_hist_t *q_hist)
312 {
313  q_hist->ocs = ocs;
314  if (q_hist->q_hist != NULL) {
315  /* Setup is already done */
316  ocs_log_debug(ocs, "q_hist not NULL, skipping init\n");
317  return;
318  }
319 
320  q_hist->q_hist = ocs_malloc(ocs, sizeof(*q_hist->q_hist)*OCS_Q_HIST_SIZE, OCS_M_ZERO | OCS_M_NOWAIT);
321 
322  if (q_hist->q_hist == NULL) {
323  ocs_log_err(ocs, "Could not allocate queue history buffer\n");
324  } else {
325  ocs_lock_init(ocs, &q_hist->q_hist_lock, "queue history lock[%d]", ocs_instance(ocs));
326  }
327 
328  q_hist->q_hist_index = 0;
329 }
330 
331 /**
332  * @ingroup debug
333  * @brief Free resources for queue history
334  *
335  * @param q_hist Pointer to the queue history object.
336  *
337  * @return none
338  */
339 void
340 ocs_queue_history_free(ocs_hal_q_hist_t *q_hist)
341 {
342  ocs_t *ocs = q_hist->ocs;
343 
344  if (q_hist->q_hist != NULL) {
345  ocs_free(ocs, q_hist->q_hist, sizeof(*q_hist->q_hist)*OCS_Q_HIST_SIZE);
346  ocs_lock_free(&q_hist->q_hist_lock);
347  q_hist->q_hist = NULL;
348  }
349 }
350 
351 static void
352 ocs_queue_history_add_q_info(ocs_hal_q_hist_t *q_hist, uint32_t qid, uint32_t qindex)
353 {
354  if (ocs_queue_history_q_info_enabled()) {
355  /* write qid, index */
356  q_hist->q_hist[q_hist->q_hist_index] = (qid << 16) | qindex;
357  q_hist->q_hist_index++;
358  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
359  }
360 }
361 
362 static void
363 ocs_queue_history_add_timestamp(ocs_hal_q_hist_t *q_hist)
364 {
365  if (ocs_queue_history_timestamp_enabled()) {
366  /* write tsc */
367  uint64_t tsc_value;
368  tsc_value = ocs_get_tsc();
369  q_hist->q_hist[q_hist->q_hist_index] = ((tsc_value >> 32 ) & 0xFFFFFFFF);
370  q_hist->q_hist_index++;
371  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
372  q_hist->q_hist[q_hist->q_hist_index] = (tsc_value & 0xFFFFFFFF);
373  q_hist->q_hist_index++;
374  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
375  }
376 }
377 
378 /**
379  * @ingroup debug
380  * @brief Log work queue entry (WQE) into history array
381  *
382  * @param q_hist Pointer to the queue history object.
383  * @param entryw Work queue entry in words
384  * @param qid Queue ID
385  * @param qindex Queue index
386  *
387  * @return none
388  */
389 void
390 ocs_queue_history_wq(ocs_hal_q_hist_t *q_hist, uint32_t *entryw, uint32_t qid, uint32_t qindex)
391 {
392  int i;
393  ocs_q_hist_ftr_t ftr;
394  uint32_t wqe_word_mask = ocs_q_hist_get_wqe_mask((sli4_skh_wqe_unassisted_t *)entryw);
395 
396  if (q_hist->q_hist == NULL) {
397  /* Can't save anything */
398  return;
399  }
400 
401  ftr.word = 0;
402  ftr.s.type = OCS_Q_HIST_TYPE_WQE;
403  ocs_lock(&q_hist->q_hist_lock);
404  /* Capture words in reverse order since we'll be interpretting them LIFO */
405  for (i = ((sizeof(wqe_word_mask)*8) - 1); i >= 0; i--){
406  if ((wqe_word_mask >> i) & 1) {
407  q_hist->q_hist[q_hist->q_hist_index] = entryw[i];
408  q_hist->q_hist_index++;
409  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
410  }
411  }
412 
413  ocs_queue_history_add_q_info(q_hist, qid, qindex);
414  ocs_queue_history_add_timestamp(q_hist);
415 
416  /* write footer */
417  if (wqe_word_mask) {
418  ftr.s.mask = wqe_word_mask;
419  q_hist->q_hist[q_hist->q_hist_index] = ftr.word;
420  q_hist->q_hist_index++;
421  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
422  }
423 
424  ocs_unlock(&q_hist->q_hist_lock);
425 }
426 
427 /**
428  * @ingroup debug
429  * @brief Log misc words
430  *
431  * @param q_hist Pointer to the queue history object.
432  * @param entryw array of words
433  * @param num_words number of words in entryw
434  *
435  * @return none
436  */
437 void
438 ocs_queue_history_misc(ocs_hal_q_hist_t *q_hist, uint32_t *entryw, uint32_t num_words)
439 {
440  int i;
441  ocs_q_hist_ftr_t ftr;
442  uint32_t mask = 0;
443 
444  if (q_hist->q_hist == NULL) {
445  /* Can't save anything */
446  return;
447  }
448 
449  ftr.word = 0;
450  ftr.s.type = OCS_Q_HIST_TYPE_MISC;
451  ocs_lock(&q_hist->q_hist_lock);
452  /* Capture words in reverse order since we'll be interpretting them LIFO */
453  for (i = num_words-1; i >= 0; i--) {
454  q_hist->q_hist[q_hist->q_hist_index] = entryw[i];
455  q_hist->q_hist_index++;
456  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
457  mask |= BIT(i);
458  }
459 
460  ocs_queue_history_add_timestamp(q_hist);
461 
462  /* write footer */
463  if (num_words) {
464  ftr.s.mask = mask;
465  q_hist->q_hist[q_hist->q_hist_index] = ftr.word;
466  q_hist->q_hist_index++;
467  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
468  }
469 
470  ocs_unlock(&q_hist->q_hist_lock);
471 }
472 
473 /**
474  * @ingroup debug
475  * @brief Log work queue completion (CQE) entry into history
476  * array
477  *
478  * @param q_hist Pointer to the queue history object.
479  * @param ctype Type of completion entry
480  * @param entryw Completion queue entry in words
481  * @param qid Queue ID
482  * @param qindex Queue index
483  *
484  * @return none
485  */
486 void
487 ocs_queue_history_cqe(ocs_hal_q_hist_t *q_hist, uint8_t ctype, uint32_t *entryw, uint32_t qid, uint32_t qindex)
488 {
489  int i;
490  unsigned j;
491  uint32_t cqe_word_mask = 0;
492  ocs_q_hist_ftr_t ftr;
493 
494  if (q_hist->q_hist == NULL) {
495  /* Can't save anything */
496  return;
497  }
498 
499  ftr.word = 0;
500  for (j = 0; j < ARRAY_SIZE(ocs_q_hist_cqe_masks); j++) {
501  if (ocs_q_hist_cqe_masks[j].ctype == ctype) {
502  ftr.s.type = ocs_q_hist_cqe_masks[j].type;
503  cqe_word_mask = ocs_q_hist_cqe_masks[j].mask;
504  }
505  }
506  ocs_lock(&q_hist->q_hist_lock);
507  /* Capture words in reverse order since we'll be interpretting them LIFO */
508  for (i = ((sizeof(cqe_word_mask)*8) - 1); i >= 0; i--){
509  if ((cqe_word_mask >> i) & 1) {
510  q_hist->q_hist[q_hist->q_hist_index] = entryw[i];
511  q_hist->q_hist_index++;
512  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
513  }
514  }
515  ocs_queue_history_add_q_info(q_hist, qid, qindex);
516  ocs_queue_history_add_timestamp(q_hist);
517 
518  /* write footer */
519  if (cqe_word_mask) {
520  ftr.s.mask = cqe_word_mask;
521  q_hist->q_hist[q_hist->q_hist_index] = ftr.word;
522  q_hist->q_hist_index++;
523  q_hist->q_hist_index = q_hist->q_hist_index % OCS_Q_HIST_SIZE;
524  }
525 
526  ocs_unlock(&q_hist->q_hist_lock);
527 }
528 
529 /**
530  * @brief Get previous index
531  *
532  * @param index Index from which previous index is derived.
533  */
534 uint32_t
535 ocs_queue_history_prev_index(uint32_t index)
536 {
537  if (index == 0) {
538  return OCS_Q_HIST_SIZE - 1;
539  } else {
540  return index - 1;
541  }
542 }
543 
544 #endif // OCS_DEBUG_QUEUE_HISTORY
545 
#define ocs_queue_history_misc(...)
Definition: ocs_debug.h:148
#define SLI4_WQE_INI_NOP
Definition: sli4_iscsi.h:1037
#define SLI4_WQE_INI_READ
Definition: sli4_iscsi.h:1038
#define MAX_BUF_WORDS
Definition: ocs_debug.c:194
#define ocs_queue_history_wq(...)
Definition: ocs_debug.h:146
#define ocs_queue_history_init(...)
Definition: ocs_debug.h:149
sli4_qentry_e
Definition: sli4.h:1869
#define SLI4_WQE_TGT_SOS
Definition: sli4_iscsi.h:1042
#define ocs_queue_history_cqe(...)
Definition: ocs_debug.h:147
#define OCS_DEBUG_MASK
Definition: ocs_debug.c:47
#define SLI4_WQE_UNASSISTED
Definition: sli4_iscsi.h:1043
#define SLI4_WQE_TGT_DATAIN
Definition: sli4_iscsi.h:1041
#define SLI4_WQE_TGT_STS
Definition: sli4_iscsi.h:1040
void ocs_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length)
Dump 32 bit hex/ascii data.
Definition: ocs_dump32.c:72
void ocs_swap_and_dump32(uint32_t mask, ocs_os_handle_t os, const char *label, void *buf, uint32_t buf_length)
Definition: ocs_debug.c:196
#define ocs_queue_history_free(...)
Definition: ocs_debug.h:150
#define OCS_EXPORT(...)
Definition: ocs_ddump.c:842
uint32_t ocs_instance(void *os)
Return the instance index of an opaque ocs structure.
Definition: ocs_driver.c:160
#define SLI4_WQE_INI_TMF
Definition: sli4_iscsi.h:1036
#define SLI4_WQE_INI_WRITE
Definition: sli4_iscsi.h:1035
WQE used to transmit a PDU without any modificiation (TGT_DM_CMD)
#define MAX_BUF_BYTES
Dump 32 bit hex/ascii data after first swapping endianess.
Definition: ocs_debug.c:193
void ocs_debug_enable(uint32_t mask)
enable debug options
Definition: ocs_debug.c:91
int ocs_debug_is_enabled(uint32_t mask)
return true if debug bits are enabled
Definition: ocs_debug.c:122
static uint32_t ocs_debug_mask
Definition: ocs_debug.c:57
#define SLI4_WQE_CONTEXT_UPDATE
Definition: sli4_iscsi.h:1039
void ocs_debug_disable(uint32_t mask)
disable debug options
Definition: ocs_debug.c:106