1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Inc. nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
49 * Interface to the hardware Packet Order / Work unit.
51 * <hr>$Revision: 29727 $<hr>
59 * This structure stores the internal POW state captured by
60 * cvmx_pow_capture(). It is purposely not exposed to the user
61 * since the format may change without notice.
65 cvmx_pow_tag_load_resp_t sstatus[CVMX_MAX_CORES][8];
66 cvmx_pow_tag_load_resp_t smemload[2048][8];
67 cvmx_pow_tag_load_resp_t sindexload[64][8];
72 CVMX_POW_LIST_UNKNOWN=0,
74 CVMX_POW_LIST_INPUT=2,
75 CVMX_POW_LIST_CORE=CVMX_POW_LIST_INPUT+8,
76 CVMX_POW_LIST_DESCHED=CVMX_POW_LIST_CORE+32,
77 CVMX_POW_LIST_NOSCHED=CVMX_POW_LIST_DESCHED+64,
78 } __cvmx_pow_list_types_t;
80 static const char *__cvmx_pow_list_names[] = {
83 "Queue 0", "Queue 1", "Queue 2", "Queue 3",
84 "Queue 4", "Queue 5", "Queue 6", "Queue 7",
85 "Core 0", "Core 1", "Core 2", "Core 3",
86 "Core 4", "Core 5", "Core 6", "Core 7",
87 "Core 8", "Core 9", "Core 10", "Core 11",
88 "Core 12", "Core 13", "Core 14", "Core 15",
89 "Core 16", "Core 17", "Core 18", "Core 19",
90 "Core 20", "Core 21", "Core 22", "Core 23",
91 "Core 24", "Core 25", "Core 26", "Core 27",
92 "Core 28", "Core 29", "Core 30", "Core 31",
93 "Desched 0", "Desched 1", "Desched 2", "Desched 3",
94 "Desched 4", "Desched 5", "Desched 6", "Desched 7",
95 "Desched 8", "Desched 9", "Desched 10", "Desched 11",
96 "Desched 12", "Desched 13", "Desched 14", "Desched 15",
97 "Desched 16", "Desched 17", "Desched 18", "Desched 19",
98 "Desched 20", "Desched 21", "Desched 22", "Desched 23",
99 "Desched 24", "Desched 25", "Desched 26", "Desched 27",
100 "Desched 28", "Desched 29", "Desched 30", "Desched 31",
101 "Desched 32", "Desched 33", "Desched 34", "Desched 35",
102 "Desched 36", "Desched 37", "Desched 38", "Desched 39",
103 "Desched 40", "Desched 41", "Desched 42", "Desched 43",
104 "Desched 44", "Desched 45", "Desched 46", "Desched 47",
105 "Desched 48", "Desched 49", "Desched 50", "Desched 51",
106 "Desched 52", "Desched 53", "Desched 54", "Desched 55",
107 "Desched 56", "Desched 57", "Desched 58", "Desched 59",
108 "Desched 60", "Desched 61", "Desched 62", "Desched 63",
114 * Return the number of POW entries supported by this chip
116 * @return Number of POW entries
118 int cvmx_pow_get_num_entries(void)
120 if (OCTEON_IS_MODEL(OCTEON_CN30XX))
122 else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN50XX))
124 else if (OCTEON_IS_MODEL(OCTEON_CN52XX)
125 || OCTEON_IS_MODEL(OCTEON_CN61XX)
126 || OCTEON_IS_MODEL(OCTEON_CNF71XX))
128 else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX))
135 static int __cvmx_pow_capture_v1(void *buffer, int buffer_size)
137 __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer;
139 int num_pow_entries = cvmx_pow_get_num_entries();
144 if (buffer_size < (int)sizeof(__cvmx_pow_dump_t))
146 cvmx_dprintf("cvmx_pow_capture: Buffer too small\n");
150 num_cores = cvmx_octeon_num_cores();
152 /* Read all core related state */
153 for (core=0; core<num_cores; core++)
155 cvmx_pow_load_addr_t load_addr;
157 load_addr.sstatus.mem_region = CVMX_IO_SEG;
158 load_addr.sstatus.is_io = 1;
159 load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1;
160 load_addr.sstatus.coreid = core;
161 for (bits=0; bits<8; bits++)
163 load_addr.sstatus.get_rev = (bits & 1) != 0;
164 load_addr.sstatus.get_cur = (bits & 2) != 0;
165 load_addr.sstatus.get_wqp = (bits & 4) != 0;
166 if ((load_addr.sstatus.get_cur == 0) && load_addr.sstatus.get_rev)
167 dump->sstatus[core][bits].u64 = -1;
169 dump->sstatus[core][bits].u64 = cvmx_read_csr(load_addr.u64);
173 /* Read all internal POW entries */
174 for (index=0; index<num_pow_entries; index++)
176 cvmx_pow_load_addr_t load_addr;
178 load_addr.smemload.mem_region = CVMX_IO_SEG;
179 load_addr.smemload.is_io = 1;
180 load_addr.smemload.did = CVMX_OCT_DID_TAG_TAG2;
181 load_addr.smemload.index = index;
182 for (bits=0; bits<3; bits++)
184 load_addr.smemload.get_des = (bits & 1) != 0;
185 load_addr.smemload.get_wqp = (bits & 2) != 0;
186 dump->smemload[index][bits].u64 = cvmx_read_csr(load_addr.u64);
190 /* Read all group and queue pointers */
191 for (index=0; index<16; index++)
193 cvmx_pow_load_addr_t load_addr;
195 load_addr.sindexload.mem_region = CVMX_IO_SEG;
196 load_addr.sindexload.is_io = 1;
197 load_addr.sindexload.did = CVMX_OCT_DID_TAG_TAG3;
198 load_addr.sindexload.qosgrp = index;
199 for (bits=0; bits<4; bits++)
201 load_addr.sindexload.get_rmt = (bits & 1) != 0;
202 load_addr.sindexload.get_des_get_tail = (bits & 2) != 0;
203 /* The first pass only has 8 valid index values */
204 if ((load_addr.sindexload.get_rmt == 0) &&
205 (load_addr.sindexload.get_des_get_tail == 0) &&
207 dump->sindexload[index][bits].u64 = -1;
209 dump->sindexload[index][bits].u64 = cvmx_read_csr(load_addr.u64);
215 static int __cvmx_pow_capture_v2(void *buffer, int buffer_size)
217 __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer;
219 int num_pow_entries = cvmx_pow_get_num_entries();
224 if (buffer_size < (int)sizeof(__cvmx_pow_dump_t))
226 cvmx_dprintf("cvmx_pow_capture: Buffer too small\n");
230 num_cores = cvmx_octeon_num_cores();
232 /* Read all core related state */
233 for (core=0; core<num_cores; core++)
235 cvmx_pow_load_addr_t load_addr;
237 load_addr.sstatus_cn68xx.mem_region = CVMX_IO_SEG;
238 load_addr.sstatus_cn68xx.is_io = 1;
239 load_addr.sstatus_cn68xx.did = CVMX_OCT_DID_TAG_TAG5;
240 load_addr.sstatus_cn68xx.coreid = core;
241 for (bits=1; bits<6; bits++)
243 load_addr.sstatus_cn68xx.opcode = bits;
244 dump->sstatus[core][bits].u64 = cvmx_read_csr(load_addr.u64);
247 /* Read all internal POW entries */
248 for (index=0; index<num_pow_entries; index++)
250 cvmx_pow_load_addr_t load_addr;
252 load_addr.smemload_cn68xx.mem_region = CVMX_IO_SEG;
253 load_addr.smemload_cn68xx.is_io = 1;
254 load_addr.smemload_cn68xx.did = CVMX_OCT_DID_TAG_TAG2;
255 load_addr.smemload_cn68xx.index = index;
256 for (bits=1; bits<5; bits++)
258 load_addr.smemload_cn68xx.opcode = bits;
259 dump->smemload[index][bits].u64 = cvmx_read_csr(load_addr.u64);
263 /* Read all group and queue pointers */
264 for (index=0; index<64; index++)
266 cvmx_pow_load_addr_t load_addr;
268 load_addr.sindexload_cn68xx.mem_region = CVMX_IO_SEG;
269 load_addr.sindexload_cn68xx.is_io = 1;
270 load_addr.sindexload_cn68xx.did = CVMX_OCT_DID_TAG_TAG3;
271 load_addr.sindexload_cn68xx.qos_grp = index;
272 for (bits=1; bits<7; bits++)
274 load_addr.sindexload_cn68xx.opcode = bits;
275 dump->sindexload[index][bits].u64 = cvmx_read_csr(load_addr.u64);
282 * Store the current POW internal state into the supplied
283 * buffer. It is recommended that you pass a buffer of at least
284 * 128KB. The format of the capture may change based on SDK
285 * version and Octeon chip.
287 * @param buffer Buffer to store capture into
289 * The size of the supplied buffer
291 * @return Zero on sucess, negative on failure
293 int cvmx_pow_capture(void *buffer, int buffer_size)
295 if (octeon_has_feature(OCTEON_FEATURE_PKND))
296 return __cvmx_pow_capture_v2(buffer, buffer_size);
298 return __cvmx_pow_capture_v1(buffer, buffer_size);
302 * Function to display a POW internal queue to the user
304 * @param name User visible name for the queue
305 * @param name_param Parameter for printf in creating the name
306 * @param valid Set if the queue contains any elements
307 * @param has_one Set if the queue contains exactly one element
308 * @param head The head pointer
309 * @param tail The tail pointer
311 static void __cvmx_pow_display_list(const char *name, int name_param, int valid, int has_one, uint64_t head, uint64_t tail)
313 printf(name, name_param);
318 printf("One element index=%llu(0x%llx)\n", CAST64(head), CAST64(head));
320 printf("Multiple elements head=%llu(0x%llx) tail=%llu(0x%llx)\n", CAST64(head), CAST64(head), CAST64(tail), CAST64(tail));
328 * Mark which list a POW entry is on. Print a warning message if the
329 * entry is already on a list. This happens if the POW changed while
330 * the capture was running.
332 * @param entry_num Entry number to mark
333 * @param entry_type List type
334 * @param entry_list Array to store marks
336 * @return Zero on success, negative if already on a list
338 static int __cvmx_pow_entry_mark_list(int entry_num, __cvmx_pow_list_types_t entry_type, uint8_t entry_list[])
340 if (entry_list[entry_num] == 0)
342 entry_list[entry_num] = entry_type;
347 printf("\nWARNING: Entry %d already on list %s, but we tried to add it to %s\n",
348 entry_num, __cvmx_pow_list_names[entry_list[entry_num]], __cvmx_pow_list_names[entry_type]);
355 * Display a list and mark all elements on the list as belonging to
358 * @param entry_type Type of the list to display and mark
359 * @param dump POW capture data
360 * @param entry_list Array to store marks in
361 * @param valid Set if the queue contains any elements
362 * @param has_one Set if the queue contains exactly one element
363 * @param head The head pointer
364 * @param tail The tail pointer
366 static void __cvmx_pow_display_list_and_walk(__cvmx_pow_list_types_t entry_type,
367 __cvmx_pow_dump_t *dump, uint8_t entry_list[],
368 int valid, int has_one, uint64_t head, uint64_t tail)
370 __cvmx_pow_display_list(__cvmx_pow_list_names[entry_type], 0, valid, has_one, head, tail);
374 __cvmx_pow_entry_mark_list(head, entry_type, entry_list);
379 if (__cvmx_pow_entry_mark_list(head, entry_type, entry_list))
381 if (octeon_has_feature(OCTEON_FEATURE_PKND))
383 if (entry_type >= CVMX_POW_LIST_INPUT && entry_type < CVMX_POW_LIST_CORE)
385 head = dump->smemload[head][4].s_smemload3_cn68xx.next_index;
387 head = dump->smemload[head][4].s_smemload3_cn68xx.fwd_index;
390 head = dump->smemload[head][0].s_smemload0.next_index;
392 __cvmx_pow_entry_mark_list(tail, entry_type, entry_list);
398 void __cvmx_pow_display_v1(void *buffer, int buffer_size)
400 __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer;
401 int num_pow_entries = cvmx_pow_get_num_entries();
405 uint8_t entry_list[2048];
407 if (buffer_size < (int)sizeof(__cvmx_pow_dump_t))
409 cvmx_dprintf("cvmx_pow_dump: Buffer too small\n");
413 memset(entry_list, 0, sizeof(entry_list));
414 num_cores = cvmx_octeon_num_cores();
416 /* Print the free list info */
417 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_FREE, dump, entry_list,
418 dump->sindexload[0][0].sindexload0.free_val,
419 dump->sindexload[0][0].sindexload0.free_one,
420 dump->sindexload[0][0].sindexload0.free_head,
421 dump->sindexload[0][0].sindexload0.free_tail);
423 /* Print the core state */
424 for (core=0; core<num_cores; core++)
426 const int bit_rev = 1;
427 const int bit_cur = 2;
428 const int bit_wqp = 4;
429 printf("Core %d State: tag=%s,0x%08x", core,
430 OCT_TAG_TYPE_STRING(dump->sstatus[core][bit_cur].s_sstatus2.tag_type),
431 dump->sstatus[core][bit_cur].s_sstatus2.tag);
432 if (dump->sstatus[core][bit_cur].s_sstatus2.tag_type != CVMX_POW_TAG_TYPE_NULL_NULL)
434 __cvmx_pow_entry_mark_list(dump->sstatus[core][bit_cur].s_sstatus2.index, CVMX_POW_LIST_CORE + core, entry_list);
435 printf(" grp=%d", dump->sstatus[core][bit_cur].s_sstatus2.grp);
436 printf(" wqp=0x%016llx", CAST64(dump->sstatus[core][bit_cur|bit_wqp].s_sstatus4.wqp));
437 printf(" index=%d", dump->sstatus[core][bit_cur].s_sstatus2.index);
438 if (dump->sstatus[core][bit_cur].s_sstatus2.head)
441 printf(" prev=%d", dump->sstatus[core][bit_cur|bit_rev].s_sstatus3.revlink_index);
442 if (dump->sstatus[core][bit_cur].s_sstatus2.tail)
445 printf(" next=%d", dump->sstatus[core][bit_cur].s_sstatus2.link_index);
448 if (dump->sstatus[core][0].s_sstatus0.pend_switch)
450 printf(" pend_switch=%d", dump->sstatus[core][0].s_sstatus0.pend_switch);
451 printf(" pend_switch_full=%d", dump->sstatus[core][0].s_sstatus0.pend_switch_full);
452 printf(" pend_switch_null=%d", dump->sstatus[core][0].s_sstatus0.pend_switch_null);
455 if (dump->sstatus[core][0].s_sstatus0.pend_desched)
457 printf(" pend_desched=%d", dump->sstatus[core][0].s_sstatus0.pend_desched);
458 printf(" pend_desched_switch=%d", dump->sstatus[core][0].s_sstatus0.pend_desched_switch);
459 printf(" pend_nosched=%d", dump->sstatus[core][0].s_sstatus0.pend_nosched);
460 if (dump->sstatus[core][0].s_sstatus0.pend_desched_switch)
461 printf(" pend_grp=%d", dump->sstatus[core][0].s_sstatus0.pend_grp);
464 if (dump->sstatus[core][0].s_sstatus0.pend_new_work)
466 if (dump->sstatus[core][0].s_sstatus0.pend_new_work_wait)
467 printf(" (Waiting for work)");
469 printf(" (Getting work)");
471 if (dump->sstatus[core][0].s_sstatus0.pend_null_rd)
472 printf(" pend_null_rd=%d", dump->sstatus[core][0].s_sstatus0.pend_null_rd);
473 if (dump->sstatus[core][0].s_sstatus0.pend_nosched_clr)
475 printf(" pend_nosched_clr=%d", dump->sstatus[core][0].s_sstatus0.pend_nosched_clr);
476 printf(" pend_index=%d", dump->sstatus[core][0].s_sstatus0.pend_index);
478 if (dump->sstatus[core][0].s_sstatus0.pend_switch ||
479 (dump->sstatus[core][0].s_sstatus0.pend_desched &&
480 dump->sstatus[core][0].s_sstatus0.pend_desched_switch))
482 printf(" pending tag=%s,0x%08x",
483 OCT_TAG_TYPE_STRING(dump->sstatus[core][0].s_sstatus0.pend_type),
484 dump->sstatus[core][0].s_sstatus0.pend_tag);
486 if (dump->sstatus[core][0].s_sstatus0.pend_nosched_clr)
487 printf(" pend_wqp=0x%016llx\n", CAST64(dump->sstatus[core][bit_wqp].s_sstatus1.pend_wqp));
491 /* Print out the state of the nosched list and the 16 deschedule lists. */
492 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_NOSCHED, dump, entry_list,
493 dump->sindexload[0][2].sindexload1.nosched_val,
494 dump->sindexload[0][2].sindexload1.nosched_one,
495 dump->sindexload[0][2].sindexload1.nosched_head,
496 dump->sindexload[0][2].sindexload1.nosched_tail);
497 for (index=0; index<16; index++)
499 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_DESCHED + index, dump, entry_list,
500 dump->sindexload[index][2].sindexload1.des_val,
501 dump->sindexload[index][2].sindexload1.des_one,
502 dump->sindexload[index][2].sindexload1.des_head,
503 dump->sindexload[index][2].sindexload1.des_tail);
506 /* Print out the state of the 8 internal input queues */
507 for (index=0; index<8; index++)
509 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_INPUT + index, dump, entry_list,
510 dump->sindexload[index][0].sindexload0.loc_val,
511 dump->sindexload[index][0].sindexload0.loc_one,
512 dump->sindexload[index][0].sindexload0.loc_head,
513 dump->sindexload[index][0].sindexload0.loc_tail);
516 /* Print out the state of the 16 memory queues */
517 for (index=0; index<8; index++)
520 if (dump->sindexload[index][1].sindexload2.rmt_is_head)
521 name = "Queue %da Memory (is head)";
523 name = "Queue %da Memory";
524 __cvmx_pow_display_list(name, index,
525 dump->sindexload[index][1].sindexload2.rmt_val,
526 dump->sindexload[index][1].sindexload2.rmt_one,
527 dump->sindexload[index][1].sindexload2.rmt_head,
528 dump->sindexload[index][3].sindexload3.rmt_tail);
529 if (dump->sindexload[index+8][1].sindexload2.rmt_is_head)
530 name = "Queue %db Memory (is head)";
532 name = "Queue %db Memory";
533 __cvmx_pow_display_list(name, index,
534 dump->sindexload[index+8][1].sindexload2.rmt_val,
535 dump->sindexload[index+8][1].sindexload2.rmt_one,
536 dump->sindexload[index+8][1].sindexload2.rmt_head,
537 dump->sindexload[index+8][3].sindexload3.rmt_tail);
540 /* Print out each of the internal POW entries. Each entry has a tag, group,
541 wqe, and possibly a next pointer. The next pointer is only valid if this
542 entry isn't make as a tail */
543 for (index=0; index<num_pow_entries; index++)
545 printf("Entry %d(%-10s): tag=%s,0x%08x grp=%d wqp=0x%016llx", index,
546 __cvmx_pow_list_names[entry_list[index]],
547 OCT_TAG_TYPE_STRING(dump->smemload[index][0].s_smemload0.tag_type),
548 dump->smemload[index][0].s_smemload0.tag,
549 dump->smemload[index][0].s_smemload0.grp,
550 CAST64(dump->smemload[index][2].s_smemload1.wqp));
551 if (dump->smemload[index][0].s_smemload0.tail)
554 printf(" next=%d", dump->smemload[index][0].s_smemload0.next_index);
555 if (entry_list[index] >= CVMX_POW_LIST_DESCHED)
557 printf(" nosched=%d", dump->smemload[index][1].s_smemload2.nosched);
558 if (dump->smemload[index][1].s_smemload2.pend_switch)
560 printf(" pending tag=%s,0x%08x",
561 OCT_TAG_TYPE_STRING(dump->smemload[index][1].s_smemload2.pend_type),
562 dump->smemload[index][1].s_smemload2.pend_tag);
569 void __cvmx_pow_display_v2(void *buffer, int buffer_size)
571 __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer;
572 int num_pow_entries = cvmx_pow_get_num_entries();
576 uint8_t entry_list[2048];
578 if (buffer_size < (int)sizeof(__cvmx_pow_dump_t))
580 cvmx_dprintf("cvmx_pow_dump: Buffer too small, pow_dump_t = 0x%x, buffer_size = 0x%x\n", (int)sizeof(__cvmx_pow_dump_t), buffer_size);
584 memset(entry_list, 0, sizeof(entry_list));
585 num_cores = cvmx_octeon_num_cores();
587 /* Print the free list info */
589 int valid[3], has_one[3], head[3], tail[3], qnum_head, qnum_tail;
592 valid[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_val;
593 valid[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_val;
594 valid[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_val;
595 has_one[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_one;
596 has_one[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_one;
597 has_one[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_one;
598 head[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_head;
599 head[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_head;
600 head[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_head;
601 tail[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_tail;
602 tail[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_tail;
603 tail[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_tail;
604 qnum_head = dump->sindexload[0][4].sindexload1_cn68xx.qnum_head;
605 qnum_tail = dump->sindexload[0][4].sindexload1_cn68xx.qnum_tail;
607 printf("Free List: qnum_head=%d, qnum_tail=%d\n", qnum_head, qnum_tail);
608 printf("Free0: valid=%d, one=%d, head=%llu, tail=%llu\n", valid[0], has_one[0], CAST64(head[0]), CAST64(tail[0]));
609 printf("Free1: valid=%d, one=%d, head=%llu, tail=%llu\n", valid[1], has_one[1], CAST64(head[1]), CAST64(tail[1]));
610 printf("Free2: valid=%d, one=%d, head=%llu, tail=%llu\n", valid[2], has_one[2], CAST64(head[2]), CAST64(tail[2]));
613 while (valid[0] || valid[1] || valid[2])
617 if (head[qidx] == tail[qidx])
620 if (__cvmx_pow_entry_mark_list(head[qidx], CVMX_POW_LIST_FREE, entry_list))
622 head[qidx] = dump->smemload[head[qidx]][4].s_smemload3_cn68xx.fwd_index;
623 //printf("qidx = %d, idx = %d, head[qidx] = %d\n", qidx, idx, head[qidx]);
628 /* Print the core state */
629 for (core = 0; core < num_cores; core++)
637 printf("Core %d State: tag=%s,0x%08x", core,
638 OCT_TAG_TYPE_STRING(dump->sstatus[core][tag].s_sstatus2_cn68xx.tag_type),
639 dump->sstatus[core][tag].s_sstatus2_cn68xx.tag);
640 if (dump->sstatus[core][tag].s_sstatus2_cn68xx.tag_type != CVMX_POW_TAG_TYPE_NULL_NULL)
642 __cvmx_pow_entry_mark_list(dump->sstatus[core][tag].s_sstatus2_cn68xx.index, CVMX_POW_LIST_CORE + core, entry_list);
643 printf(" grp=%d", dump->sstatus[core][tag].s_sstatus2_cn68xx.grp);
644 printf(" wqp=0x%016llx", CAST64(dump->sstatus[core][wqp].s_sstatus3_cn68xx.wqp));
645 printf(" index=%d", dump->sstatus[core][tag].s_sstatus2_cn68xx.index);
646 if (dump->sstatus[core][links].s_sstatus4_cn68xx.head)
649 printf(" prev=%d", dump->sstatus[core][links].s_sstatus4_cn68xx.revlink_index);
650 if (dump->sstatus[core][links].s_sstatus4_cn68xx.tail)
653 printf(" next=%d", dump->sstatus[core][links].s_sstatus4_cn68xx.link_index);
655 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_switch)
657 printf(" pend_switch=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_switch);
660 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_desched)
662 printf(" pend_desched=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_desched);
663 printf(" pend_nosched=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_nosched);
665 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_get_work)
667 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_get_work_wait)
668 printf(" (Waiting for work)");
670 printf(" (Getting work)");
672 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_alloc_we)
673 printf(" pend_alloc_we=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_alloc_we);
674 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_nosched_clr)
676 printf(" pend_nosched_clr=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_nosched_clr);
677 printf(" pend_index=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_index);
679 if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_switch)
681 printf(" pending tag=%s,0x%08x",
682 OCT_TAG_TYPE_STRING(dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_type),
683 dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_tag);
685 if (dump->sstatus[core][pendwqp].s_sstatus1_cn68xx.pend_nosched_clr)
686 printf(" pend_wqp=0x%016llx\n", CAST64(dump->sstatus[core][pendwqp].s_sstatus1_cn68xx.pend_wqp));
690 /* Print out the state of the nosched list and the 16 deschedule lists. */
691 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_NOSCHED, dump, entry_list,
692 dump->sindexload[0][3].sindexload0_cn68xx.queue_val,
693 dump->sindexload[0][3].sindexload0_cn68xx.queue_one,
694 dump->sindexload[0][3].sindexload0_cn68xx.queue_head,
695 dump->sindexload[0][3].sindexload0_cn68xx.queue_tail);
696 for (index=0; index<64; index++)
698 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_DESCHED + index, dump, entry_list,
699 dump->sindexload[index][2].sindexload0_cn68xx.queue_val,
700 dump->sindexload[index][2].sindexload0_cn68xx.queue_one,
701 dump->sindexload[index][2].sindexload0_cn68xx.queue_head,
702 dump->sindexload[index][2].sindexload0_cn68xx.queue_tail);
705 /* Print out the state of the 8 internal input queues */
706 for (index=0; index<8; index++)
708 __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_INPUT + index, dump, entry_list,
709 dump->sindexload[index][1].sindexload0_cn68xx.queue_val,
710 dump->sindexload[index][1].sindexload0_cn68xx.queue_one,
711 dump->sindexload[index][1].sindexload0_cn68xx.queue_head,
712 dump->sindexload[index][1].sindexload0_cn68xx.queue_tail);
715 /* Print out the state of the 16 memory queues */
716 for (index=0; index<8; index++)
719 if (dump->sindexload[index][1].sindexload0_cn68xx.queue_head)
720 name = "Queue %da Memory (is head)";
722 name = "Queue %da Memory";
723 __cvmx_pow_display_list(name, index,
724 dump->sindexload[index][1].sindexload0_cn68xx.queue_val,
725 dump->sindexload[index][1].sindexload0_cn68xx.queue_one,
726 dump->sindexload[index][1].sindexload0_cn68xx.queue_head,
727 dump->sindexload[index][1].sindexload0_cn68xx.queue_tail);
728 if (dump->sindexload[index+8][1].sindexload0_cn68xx.queue_head)
729 name = "Queue %db Memory (is head)";
731 name = "Queue %db Memory";
732 __cvmx_pow_display_list(name, index,
733 dump->sindexload[index+8][1].sindexload0_cn68xx.queue_val,
734 dump->sindexload[index+8][1].sindexload0_cn68xx.queue_one,
735 dump->sindexload[index+8][1].sindexload0_cn68xx.queue_head,
736 dump->sindexload[index+8][1].sindexload0_cn68xx.queue_tail);
739 /* Print out each of the internal POW entries. Each entry has a tag, group,
740 wqe, and possibly a next pointer. The next pointer is only valid if this
741 entry isn't make as a tail */
742 for (index=0; index<num_pow_entries; index++)
744 printf("Entry %d(%-10s): tag=%s,0x%08x grp=%d wqp=0x%016llx", index,
745 __cvmx_pow_list_names[entry_list[index]],
746 OCT_TAG_TYPE_STRING(dump->smemload[index][1].s_smemload0_cn68xx.tag_type),
747 dump->smemload[index][1].s_smemload0_cn68xx.tag,
748 dump->smemload[index][2].s_smemload1_cn68xx.grp,
749 CAST64(dump->smemload[index][2].s_smemload1_cn68xx.wqp));
750 if (dump->smemload[index][1].s_smemload0_cn68xx.tail)
753 printf(" next=%d", dump->smemload[index][4].s_smemload3_cn68xx.fwd_index);
754 if (entry_list[index] >= CVMX_POW_LIST_DESCHED)
756 printf(" prev=%d", dump->smemload[index][4].s_smemload3_cn68xx.fwd_index);
757 printf(" nosched=%d", dump->smemload[index][1].s_smemload1_cn68xx.nosched);
758 if (dump->smemload[index][3].s_smemload2_cn68xx.pend_switch)
760 printf(" pending tag=%s,0x%08x",
761 OCT_TAG_TYPE_STRING(dump->smemload[index][3].s_smemload2_cn68xx.pend_type),
762 dump->smemload[index][3].s_smemload2_cn68xx.pend_tag);
770 * Dump a POW capture to the console in a human readable format.
772 * @param buffer POW capture from cvmx_pow_capture()
776 void cvmx_pow_display(void *buffer, int buffer_size)
778 printf("POW Display Start\n");
780 if (octeon_has_feature(OCTEON_FEATURE_PKND))
781 __cvmx_pow_display_v2(buffer, buffer_size);
783 __cvmx_pow_display_v1(buffer, buffer_size);
785 printf("POW Display End\n");