cvmx-pow.c revision 302408
1151497Sru/***********************license start*************** 2151497Sru * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3151497Sru * reserved. 4151497Sru * 5151497Sru * 6151497Sru * Redistribution and use in source and binary forms, with or without 7151497Sru * modification, are permitted provided that the following conditions are 8151497Sru * met: 9151497Sru * 10151497Sru * * Redistributions of source code must retain the above copyright 11151497Sru * notice, this list of conditions and the following disclaimer. 12151497Sru * 13151497Sru * * Redistributions in binary form must reproduce the above 14151497Sru * copyright notice, this list of conditions and the following 15151497Sru * disclaimer in the documentation and/or other materials provided 16151497Sru * with the distribution. 17151497Sru 18151497Sru * * Neither the name of Cavium Inc. nor the names of 19151497Sru * its contributors may be used to endorse or promote products 20151497Sru * derived from this software without specific prior written 21151497Sru * permission. 22151497Sru 23151497Sru * This Software, including technical data, may be subject to U.S. export control 24151497Sru * laws, including the U.S. Export Administration Act and its associated 25151497Sru * regulations, and may be subject to export or import regulations in other 26151497Sru * countries. 27151497Sru 28151497Sru * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29151497Sru * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30151497Sru * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31151497Sru * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32151497Sru * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33151497Sru * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34151497Sru * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35151497Sru * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36151497Sru * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37151497Sru * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38151497Sru ***********************license end**************************************/ 39151497Sru 40151497Sru 41151497Sru 42151497Sru 43151497Sru 44151497Sru 45151497Sru 46151497Sru/** 47151497Sru * @file 48151497Sru * 49151497Sru * Interface to the hardware Packet Order / Work unit. 50151497Sru * 51151497Sru * <hr>$Revision: 29727 $<hr> 52151497Sru */ 53151497Sru 54151497Sru#include "cvmx.h" 55151497Sru#include "cvmx-pow.h" 56151497Sru 57151497Sru/** 58151497Sru * @INTERNAL 59151497Sru * This structure stores the internal POW state captured by 60151497Sru * cvmx_pow_capture(). It is purposely not exposed to the user 61151497Sru * since the format may change without notice. 62151497Sru */ 63151497Srutypedef struct 64151497Sru{ 65151497Sru cvmx_pow_tag_load_resp_t sstatus[CVMX_MAX_CORES][8]; 66151497Sru cvmx_pow_tag_load_resp_t smemload[2048][8]; 67151497Sru cvmx_pow_tag_load_resp_t sindexload[64][8]; 68151497Sru} __cvmx_pow_dump_t; 69151497Sru 70151497Srutypedef enum 71151497Sru{ 72151497Sru CVMX_POW_LIST_UNKNOWN=0, 73151497Sru CVMX_POW_LIST_FREE=1, 74151497Sru CVMX_POW_LIST_INPUT=2, 75151497Sru CVMX_POW_LIST_CORE=CVMX_POW_LIST_INPUT+8, 76151497Sru CVMX_POW_LIST_DESCHED=CVMX_POW_LIST_CORE+32, 77151497Sru CVMX_POW_LIST_NOSCHED=CVMX_POW_LIST_DESCHED+64, 78151497Sru} __cvmx_pow_list_types_t; 79151497Sru 80151497Srustatic const char *__cvmx_pow_list_names[] = { 81151497Sru "Unknown", 82151497Sru "Free List", 83151497Sru "Queue 0", "Queue 1", "Queue 2", "Queue 3", 84151497Sru "Queue 4", "Queue 5", "Queue 6", "Queue 7", 85151497Sru "Core 0", "Core 1", "Core 2", "Core 3", 86151497Sru "Core 4", "Core 5", "Core 6", "Core 7", 87151497Sru "Core 8", "Core 9", "Core 10", "Core 11", 88151497Sru "Core 12", "Core 13", "Core 14", "Core 15", 89151497Sru "Core 16", "Core 17", "Core 18", "Core 19", 90151497Sru "Core 20", "Core 21", "Core 22", "Core 23", 91151497Sru "Core 24", "Core 25", "Core 26", "Core 27", 92151497Sru "Core 28", "Core 29", "Core 30", "Core 31", 93151497Sru "Desched 0", "Desched 1", "Desched 2", "Desched 3", 94151497Sru "Desched 4", "Desched 5", "Desched 6", "Desched 7", 95151497Sru "Desched 8", "Desched 9", "Desched 10", "Desched 11", 96151497Sru "Desched 12", "Desched 13", "Desched 14", "Desched 15", 97151497Sru "Desched 16", "Desched 17", "Desched 18", "Desched 19", 98151497Sru "Desched 20", "Desched 21", "Desched 22", "Desched 23", 99151497Sru "Desched 24", "Desched 25", "Desched 26", "Desched 27", 100151497Sru "Desched 28", "Desched 29", "Desched 30", "Desched 31", 101151497Sru "Desched 32", "Desched 33", "Desched 34", "Desched 35", 102151497Sru "Desched 36", "Desched 37", "Desched 38", "Desched 39", 103151497Sru "Desched 40", "Desched 41", "Desched 42", "Desched 43", 104151497Sru "Desched 44", "Desched 45", "Desched 46", "Desched 47", 105151497Sru "Desched 48", "Desched 49", "Desched 50", "Desched 51", 106151497Sru "Desched 52", "Desched 53", "Desched 54", "Desched 55", 107151497Sru "Desched 56", "Desched 57", "Desched 58", "Desched 59", 108151497Sru "Desched 60", "Desched 61", "Desched 62", "Desched 63", 109151497Sru "Nosched 0" 110151497Sru}; 111151497Sru 112151497Sru 113151497Sru/** 114151497Sru * Return the number of POW entries supported by this chip 115151497Sru * 116151497Sru * @return Number of POW entries 117151497Sru */ 118151497Sruint cvmx_pow_get_num_entries(void) 119151497Sru{ 120151497Sru if (OCTEON_IS_MODEL(OCTEON_CN30XX)) 121151497Sru return 64; 122151497Sru else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) 123151497Sru return 256; 124151497Sru else if (OCTEON_IS_MODEL(OCTEON_CN52XX) 125151497Sru || OCTEON_IS_MODEL(OCTEON_CN61XX) 126151497Sru || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 127151497Sru return 512; 128151497Sru else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CN66XX)) 129151497Sru return 1024; 130151497Sru else 131151497Sru return 2048; 132151497Sru} 133151497Sru 134151497Sru 135151497Srustatic int __cvmx_pow_capture_v1(void *buffer, int buffer_size) 136151497Sru{ 137151497Sru __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer; 138151497Sru int num_cores; 139151497Sru int num_pow_entries = cvmx_pow_get_num_entries(); 140151497Sru int core; 141151497Sru int index; 142151497Sru int bits; 143151497Sru 144151497Sru if (buffer_size < (int)sizeof(__cvmx_pow_dump_t)) 145151497Sru { 146151497Sru cvmx_dprintf("cvmx_pow_capture: Buffer too small\n"); 147151497Sru return -1; 148151497Sru } 149151497Sru 150151497Sru num_cores = cvmx_octeon_num_cores(); 151151497Sru 152151497Sru /* Read all core related state */ 153151497Sru for (core=0; core<num_cores; core++) 154151497Sru { 155151497Sru cvmx_pow_load_addr_t load_addr; 156151497Sru load_addr.u64 = 0; 157151497Sru load_addr.sstatus.mem_region = CVMX_IO_SEG; 158151497Sru load_addr.sstatus.is_io = 1; 159151497Sru load_addr.sstatus.did = CVMX_OCT_DID_TAG_TAG1; 160151497Sru load_addr.sstatus.coreid = core; 161151497Sru for (bits=0; bits<8; bits++) 162151497Sru { 163151497Sru load_addr.sstatus.get_rev = (bits & 1) != 0; 164151497Sru load_addr.sstatus.get_cur = (bits & 2) != 0; 165151497Sru load_addr.sstatus.get_wqp = (bits & 4) != 0; 166151497Sru if ((load_addr.sstatus.get_cur == 0) && load_addr.sstatus.get_rev) 167151497Sru dump->sstatus[core][bits].u64 = -1; 168151497Sru else 169151497Sru dump->sstatus[core][bits].u64 = cvmx_read_csr(load_addr.u64); 170151497Sru } 171151497Sru } 172151497Sru 173151497Sru /* Read all internal POW entries */ 174151497Sru for (index=0; index<num_pow_entries; index++) 175151497Sru { 176151497Sru cvmx_pow_load_addr_t load_addr; 177151497Sru load_addr.u64 = 0; 178151497Sru load_addr.smemload.mem_region = CVMX_IO_SEG; 179151497Sru load_addr.smemload.is_io = 1; 180151497Sru load_addr.smemload.did = CVMX_OCT_DID_TAG_TAG2; 181151497Sru load_addr.smemload.index = index; 182151497Sru for (bits=0; bits<3; bits++) 183151497Sru { 184151497Sru load_addr.smemload.get_des = (bits & 1) != 0; 185151497Sru load_addr.smemload.get_wqp = (bits & 2) != 0; 186151497Sru dump->smemload[index][bits].u64 = cvmx_read_csr(load_addr.u64); 187151497Sru } 188151497Sru } 189151497Sru 190151497Sru /* Read all group and queue pointers */ 191151497Sru for (index=0; index<16; index++) 192151497Sru { 193151497Sru cvmx_pow_load_addr_t load_addr; 194151497Sru load_addr.u64 = 0; 195151497Sru load_addr.sindexload.mem_region = CVMX_IO_SEG; 196151497Sru load_addr.sindexload.is_io = 1; 197151497Sru load_addr.sindexload.did = CVMX_OCT_DID_TAG_TAG3; 198151497Sru load_addr.sindexload.qosgrp = index; 199151497Sru for (bits=0; bits<4; bits++) 200151497Sru { 201151497Sru load_addr.sindexload.get_rmt = (bits & 1) != 0; 202151497Sru load_addr.sindexload.get_des_get_tail = (bits & 2) != 0; 203151497Sru /* The first pass only has 8 valid index values */ 204151497Sru if ((load_addr.sindexload.get_rmt == 0) && 205151497Sru (load_addr.sindexload.get_des_get_tail == 0) && 206151497Sru (index >= 8)) 207151497Sru dump->sindexload[index][bits].u64 = -1; 208151497Sru else 209151497Sru dump->sindexload[index][bits].u64 = cvmx_read_csr(load_addr.u64); 210151497Sru } 211151497Sru } 212151497Sru return 0; 213151497Sru} 214151497Sru 215151497Srustatic int __cvmx_pow_capture_v2(void *buffer, int buffer_size) 216151497Sru{ 217151497Sru __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer; 218151497Sru int num_cores; 219151497Sru int num_pow_entries = cvmx_pow_get_num_entries(); 220151497Sru int core; 221151497Sru int index; 222151497Sru int bits; 223151497Sru 224151497Sru if (buffer_size < (int)sizeof(__cvmx_pow_dump_t)) 225151497Sru { 226151497Sru cvmx_dprintf("cvmx_pow_capture: Buffer too small\n"); 227151497Sru return -1; 228151497Sru } 229151497Sru 230151497Sru num_cores = cvmx_octeon_num_cores(); 231151497Sru 232151497Sru /* Read all core related state */ 233151497Sru for (core=0; core<num_cores; core++) 234151497Sru { 235151497Sru cvmx_pow_load_addr_t load_addr; 236151497Sru load_addr.u64 = 0; 237151497Sru load_addr.sstatus_cn68xx.mem_region = CVMX_IO_SEG; 238151497Sru load_addr.sstatus_cn68xx.is_io = 1; 239151497Sru load_addr.sstatus_cn68xx.did = CVMX_OCT_DID_TAG_TAG5; 240151497Sru load_addr.sstatus_cn68xx.coreid = core; 241151497Sru for (bits=1; bits<6; bits++) 242151497Sru { 243151497Sru load_addr.sstatus_cn68xx.opcode = bits; 244151497Sru dump->sstatus[core][bits].u64 = cvmx_read_csr(load_addr.u64); 245151497Sru } 246151497Sru } 247151497Sru /* Read all internal POW entries */ 248151497Sru for (index=0; index<num_pow_entries; index++) 249151497Sru { 250151497Sru cvmx_pow_load_addr_t load_addr; 251151497Sru load_addr.u64 = 0; 252151497Sru load_addr.smemload_cn68xx.mem_region = CVMX_IO_SEG; 253151497Sru load_addr.smemload_cn68xx.is_io = 1; 254151497Sru load_addr.smemload_cn68xx.did = CVMX_OCT_DID_TAG_TAG2; 255151497Sru load_addr.smemload_cn68xx.index = index; 256151497Sru for (bits=1; bits<5; bits++) 257151497Sru { 258151497Sru load_addr.smemload_cn68xx.opcode = bits; 259151497Sru dump->smemload[index][bits].u64 = cvmx_read_csr(load_addr.u64); 260151497Sru } 261151497Sru } 262151497Sru 263151497Sru /* Read all group and queue pointers */ 264151497Sru for (index=0; index<64; index++) 265151497Sru { 266151497Sru cvmx_pow_load_addr_t load_addr; 267151497Sru load_addr.u64 = 0; 268151497Sru load_addr.sindexload_cn68xx.mem_region = CVMX_IO_SEG; 269151497Sru load_addr.sindexload_cn68xx.is_io = 1; 270151497Sru load_addr.sindexload_cn68xx.did = CVMX_OCT_DID_TAG_TAG3; 271151497Sru load_addr.sindexload_cn68xx.qos_grp = index; 272151497Sru for (bits=1; bits<7; bits++) 273151497Sru { 274151497Sru load_addr.sindexload_cn68xx.opcode = bits; 275151497Sru dump->sindexload[index][bits].u64 = cvmx_read_csr(load_addr.u64); 276151497Sru } 277151497Sru } 278151497Sru return 0; 279151497Sru} 280151497Sru 281151497Sru/** 282151497Sru * Store the current POW internal state into the supplied 283151497Sru * buffer. It is recommended that you pass a buffer of at least 284151497Sru * 128KB. The format of the capture may change based on SDK 285151497Sru * version and Octeon chip. 286151497Sru * 287151497Sru * @param buffer Buffer to store capture into 288151497Sru * @param buffer_size 289151497Sru * The size of the supplied buffer 290151497Sru * 291151497Sru * @return Zero on sucess, negative on failure 292151497Sru */ 293151497Sruint cvmx_pow_capture(void *buffer, int buffer_size) 294151497Sru{ 295151497Sru if (octeon_has_feature(OCTEON_FEATURE_PKND)) 296151497Sru return __cvmx_pow_capture_v2(buffer, buffer_size); 297151497Sru else 298151497Sru return __cvmx_pow_capture_v1(buffer, buffer_size); 299151497Sru} 300151497Sru 301151497Sru/** 302151497Sru * Function to display a POW internal queue to the user 303151497Sru * 304151497Sru * @param name User visible name for the queue 305151497Sru * @param name_param Parameter for printf in creating the name 306151497Sru * @param valid Set if the queue contains any elements 307151497Sru * @param has_one Set if the queue contains exactly one element 308151497Sru * @param head The head pointer 309151497Sru * @param tail The tail pointer 310151497Sru */ 311151497Srustatic void __cvmx_pow_display_list(const char *name, int name_param, int valid, int has_one, uint64_t head, uint64_t tail) 312151497Sru{ 313151497Sru printf(name, name_param); 314151497Sru printf(": "); 315151497Sru if (valid) 316151497Sru { 317151497Sru if (has_one) 318151497Sru printf("One element index=%llu(0x%llx)\n", CAST64(head), CAST64(head)); 319151497Sru else 320151497Sru printf("Multiple elements head=%llu(0x%llx) tail=%llu(0x%llx)\n", CAST64(head), CAST64(head), CAST64(tail), CAST64(tail)); 321151497Sru } 322151497Sru else 323151497Sru printf("Empty\n"); 324151497Sru} 325151497Sru 326151497Sru 327151497Sru/** 328151497Sru * Mark which list a POW entry is on. Print a warning message if the 329151497Sru * entry is already on a list. This happens if the POW changed while 330151497Sru * the capture was running. 331151497Sru * 332151497Sru * @param entry_num Entry number to mark 333151497Sru * @param entry_type List type 334151497Sru * @param entry_list Array to store marks 335151497Sru * 336151497Sru * @return Zero on success, negative if already on a list 337151497Sru */ 338151497Srustatic int __cvmx_pow_entry_mark_list(int entry_num, __cvmx_pow_list_types_t entry_type, uint8_t entry_list[]) 339151497Sru{ 340151497Sru if (entry_list[entry_num] == 0) 341151497Sru { 342151497Sru entry_list[entry_num] = entry_type; 343151497Sru return 0; 344151497Sru } 345151497Sru else 346151497Sru { 347151497Sru printf("\nWARNING: Entry %d already on list %s, but we tried to add it to %s\n", 348151497Sru entry_num, __cvmx_pow_list_names[entry_list[entry_num]], __cvmx_pow_list_names[entry_type]); 349151497Sru return -1; 350151497Sru } 351151497Sru} 352151497Sru 353151497Sru 354151497Sru/** 355151497Sru * Display a list and mark all elements on the list as belonging to 356151497Sru * the list. 357151497Sru * 358151497Sru * @param entry_type Type of the list to display and mark 359151497Sru * @param dump POW capture data 360151497Sru * @param entry_list Array to store marks in 361151497Sru * @param valid Set if the queue contains any elements 362151497Sru * @param has_one Set if the queue contains exactly one element 363151497Sru * @param head The head pointer 364151497Sru * @param tail The tail pointer 365151497Sru */ 366151497Srustatic void __cvmx_pow_display_list_and_walk(__cvmx_pow_list_types_t entry_type, 367151497Sru __cvmx_pow_dump_t *dump, uint8_t entry_list[], 368151497Sru int valid, int has_one, uint64_t head, uint64_t tail) 369151497Sru{ 370151497Sru __cvmx_pow_display_list(__cvmx_pow_list_names[entry_type], 0, valid, has_one, head, tail); 371151497Sru if (valid) 372151497Sru { 373151497Sru if (has_one) 374151497Sru __cvmx_pow_entry_mark_list(head, entry_type, entry_list); 375151497Sru else 376151497Sru { 377151497Sru while (head != tail) 378151497Sru { 379151497Sru if (__cvmx_pow_entry_mark_list(head, entry_type, entry_list)) 380151497Sru break; 381151497Sru if (octeon_has_feature(OCTEON_FEATURE_PKND)) 382151497Sru { 383151497Sru if (entry_type >= CVMX_POW_LIST_INPUT && entry_type < CVMX_POW_LIST_CORE) 384151497Sru 385151497Sru head = dump->smemload[head][4].s_smemload3_cn68xx.next_index; 386151497Sru else 387151497Sru head = dump->smemload[head][4].s_smemload3_cn68xx.fwd_index; 388151497Sru } 389151497Sru else 390151497Sru head = dump->smemload[head][0].s_smemload0.next_index; 391151497Sru } 392151497Sru __cvmx_pow_entry_mark_list(tail, entry_type, entry_list); 393151497Sru } 394151497Sru } 395151497Sru} 396151497Sru 397151497Sru 398151497Sruvoid __cvmx_pow_display_v1(void *buffer, int buffer_size) 399151497Sru{ 400151497Sru __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer; 401151497Sru int num_pow_entries = cvmx_pow_get_num_entries(); 402151497Sru int num_cores; 403151497Sru int core; 404151497Sru int index; 405151497Sru uint8_t entry_list[2048]; 406151497Sru 407151497Sru if (buffer_size < (int)sizeof(__cvmx_pow_dump_t)) 408151497Sru { 409151497Sru cvmx_dprintf("cvmx_pow_dump: Buffer too small\n"); 410151497Sru return; 411151497Sru } 412151497Sru 413151497Sru memset(entry_list, 0, sizeof(entry_list)); 414151497Sru num_cores = cvmx_octeon_num_cores(); 415151497Sru 416151497Sru /* Print the free list info */ 417151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_FREE, dump, entry_list, 418151497Sru dump->sindexload[0][0].sindexload0.free_val, 419151497Sru dump->sindexload[0][0].sindexload0.free_one, 420151497Sru dump->sindexload[0][0].sindexload0.free_head, 421151497Sru dump->sindexload[0][0].sindexload0.free_tail); 422151497Sru 423151497Sru /* Print the core state */ 424151497Sru for (core=0; core<num_cores; core++) 425151497Sru { 426151497Sru const int bit_rev = 1; 427151497Sru const int bit_cur = 2; 428151497Sru const int bit_wqp = 4; 429151497Sru printf("Core %d State: tag=%s,0x%08x", core, 430151497Sru OCT_TAG_TYPE_STRING(dump->sstatus[core][bit_cur].s_sstatus2.tag_type), 431151497Sru dump->sstatus[core][bit_cur].s_sstatus2.tag); 432151497Sru if (dump->sstatus[core][bit_cur].s_sstatus2.tag_type != CVMX_POW_TAG_TYPE_NULL_NULL) 433151497Sru { 434151497Sru __cvmx_pow_entry_mark_list(dump->sstatus[core][bit_cur].s_sstatus2.index, CVMX_POW_LIST_CORE + core, entry_list); 435151497Sru printf(" grp=%d", dump->sstatus[core][bit_cur].s_sstatus2.grp); 436151497Sru printf(" wqp=0x%016llx", CAST64(dump->sstatus[core][bit_cur|bit_wqp].s_sstatus4.wqp)); 437151497Sru printf(" index=%d", dump->sstatus[core][bit_cur].s_sstatus2.index); 438151497Sru if (dump->sstatus[core][bit_cur].s_sstatus2.head) 439151497Sru printf(" head"); 440151497Sru else 441151497Sru printf(" prev=%d", dump->sstatus[core][bit_cur|bit_rev].s_sstatus3.revlink_index); 442151497Sru if (dump->sstatus[core][bit_cur].s_sstatus2.tail) 443151497Sru printf(" tail"); 444151497Sru else 445151497Sru printf(" next=%d", dump->sstatus[core][bit_cur].s_sstatus2.link_index); 446151497Sru } 447151497Sru 448151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_switch) 449151497Sru { 450151497Sru printf(" pend_switch=%d", dump->sstatus[core][0].s_sstatus0.pend_switch); 451151497Sru printf(" pend_switch_full=%d", dump->sstatus[core][0].s_sstatus0.pend_switch_full); 452151497Sru printf(" pend_switch_null=%d", dump->sstatus[core][0].s_sstatus0.pend_switch_null); 453151497Sru } 454151497Sru 455151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_desched) 456151497Sru { 457151497Sru printf(" pend_desched=%d", dump->sstatus[core][0].s_sstatus0.pend_desched); 458151497Sru printf(" pend_desched_switch=%d", dump->sstatus[core][0].s_sstatus0.pend_desched_switch); 459151497Sru printf(" pend_nosched=%d", dump->sstatus[core][0].s_sstatus0.pend_nosched); 460151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_desched_switch) 461151497Sru printf(" pend_grp=%d", dump->sstatus[core][0].s_sstatus0.pend_grp); 462151497Sru } 463151497Sru 464151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_new_work) 465151497Sru { 466151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_new_work_wait) 467151497Sru printf(" (Waiting for work)"); 468151497Sru else 469151497Sru printf(" (Getting work)"); 470151497Sru } 471151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_null_rd) 472151497Sru printf(" pend_null_rd=%d", dump->sstatus[core][0].s_sstatus0.pend_null_rd); 473151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_nosched_clr) 474151497Sru { 475151497Sru printf(" pend_nosched_clr=%d", dump->sstatus[core][0].s_sstatus0.pend_nosched_clr); 476151497Sru printf(" pend_index=%d", dump->sstatus[core][0].s_sstatus0.pend_index); 477151497Sru } 478151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_switch || 479151497Sru (dump->sstatus[core][0].s_sstatus0.pend_desched && 480151497Sru dump->sstatus[core][0].s_sstatus0.pend_desched_switch)) 481151497Sru { 482151497Sru printf(" pending tag=%s,0x%08x", 483151497Sru OCT_TAG_TYPE_STRING(dump->sstatus[core][0].s_sstatus0.pend_type), 484151497Sru dump->sstatus[core][0].s_sstatus0.pend_tag); 485151497Sru } 486151497Sru if (dump->sstatus[core][0].s_sstatus0.pend_nosched_clr) 487151497Sru printf(" pend_wqp=0x%016llx\n", CAST64(dump->sstatus[core][bit_wqp].s_sstatus1.pend_wqp)); 488151497Sru printf("\n"); 489151497Sru } 490151497Sru 491151497Sru /* Print out the state of the nosched list and the 16 deschedule lists. */ 492151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_NOSCHED, dump, entry_list, 493151497Sru dump->sindexload[0][2].sindexload1.nosched_val, 494151497Sru dump->sindexload[0][2].sindexload1.nosched_one, 495151497Sru dump->sindexload[0][2].sindexload1.nosched_head, 496151497Sru dump->sindexload[0][2].sindexload1.nosched_tail); 497151497Sru for (index=0; index<16; index++) 498151497Sru { 499151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_DESCHED + index, dump, entry_list, 500151497Sru dump->sindexload[index][2].sindexload1.des_val, 501151497Sru dump->sindexload[index][2].sindexload1.des_one, 502151497Sru dump->sindexload[index][2].sindexload1.des_head, 503151497Sru dump->sindexload[index][2].sindexload1.des_tail); 504151497Sru } 505151497Sru 506151497Sru /* Print out the state of the 8 internal input queues */ 507151497Sru for (index=0; index<8; index++) 508151497Sru { 509151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_INPUT + index, dump, entry_list, 510151497Sru dump->sindexload[index][0].sindexload0.loc_val, 511151497Sru dump->sindexload[index][0].sindexload0.loc_one, 512151497Sru dump->sindexload[index][0].sindexload0.loc_head, 513151497Sru dump->sindexload[index][0].sindexload0.loc_tail); 514151497Sru } 515151497Sru 516151497Sru /* Print out the state of the 16 memory queues */ 517151497Sru for (index=0; index<8; index++) 518151497Sru { 519151497Sru const char *name; 520151497Sru if (dump->sindexload[index][1].sindexload2.rmt_is_head) 521151497Sru name = "Queue %da Memory (is head)"; 522151497Sru else 523151497Sru name = "Queue %da Memory"; 524151497Sru __cvmx_pow_display_list(name, index, 525151497Sru dump->sindexload[index][1].sindexload2.rmt_val, 526151497Sru dump->sindexload[index][1].sindexload2.rmt_one, 527151497Sru dump->sindexload[index][1].sindexload2.rmt_head, 528151497Sru dump->sindexload[index][3].sindexload3.rmt_tail); 529151497Sru if (dump->sindexload[index+8][1].sindexload2.rmt_is_head) 530151497Sru name = "Queue %db Memory (is head)"; 531151497Sru else 532151497Sru name = "Queue %db Memory"; 533151497Sru __cvmx_pow_display_list(name, index, 534151497Sru dump->sindexload[index+8][1].sindexload2.rmt_val, 535151497Sru dump->sindexload[index+8][1].sindexload2.rmt_one, 536151497Sru dump->sindexload[index+8][1].sindexload2.rmt_head, 537151497Sru dump->sindexload[index+8][3].sindexload3.rmt_tail); 538151497Sru } 539151497Sru 540151497Sru /* Print out each of the internal POW entries. Each entry has a tag, group, 541151497Sru wqe, and possibly a next pointer. The next pointer is only valid if this 542151497Sru entry isn't make as a tail */ 543151497Sru for (index=0; index<num_pow_entries; index++) 544151497Sru { 545151497Sru printf("Entry %d(%-10s): tag=%s,0x%08x grp=%d wqp=0x%016llx", index, 546151497Sru __cvmx_pow_list_names[entry_list[index]], 547151497Sru OCT_TAG_TYPE_STRING(dump->smemload[index][0].s_smemload0.tag_type), 548151497Sru dump->smemload[index][0].s_smemload0.tag, 549151497Sru dump->smemload[index][0].s_smemload0.grp, 550151497Sru CAST64(dump->smemload[index][2].s_smemload1.wqp)); 551151497Sru if (dump->smemload[index][0].s_smemload0.tail) 552151497Sru printf(" tail"); 553151497Sru else 554151497Sru printf(" next=%d", dump->smemload[index][0].s_smemload0.next_index); 555151497Sru if (entry_list[index] >= CVMX_POW_LIST_DESCHED) 556151497Sru { 557151497Sru printf(" nosched=%d", dump->smemload[index][1].s_smemload2.nosched); 558151497Sru if (dump->smemload[index][1].s_smemload2.pend_switch) 559151497Sru { 560151497Sru printf(" pending tag=%s,0x%08x", 561151497Sru OCT_TAG_TYPE_STRING(dump->smemload[index][1].s_smemload2.pend_type), 562151497Sru dump->smemload[index][1].s_smemload2.pend_tag); 563151497Sru } 564151497Sru } 565151497Sru printf("\n"); 566151497Sru } 567151497Sru} 568151497Sru 569151497Sruvoid __cvmx_pow_display_v2(void *buffer, int buffer_size) 570151497Sru{ 571151497Sru __cvmx_pow_dump_t *dump = (__cvmx_pow_dump_t*)buffer; 572151497Sru int num_pow_entries = cvmx_pow_get_num_entries(); 573151497Sru int num_cores; 574151497Sru int core; 575151497Sru int index; 576151497Sru uint8_t entry_list[2048]; 577151497Sru 578151497Sru if (buffer_size < (int)sizeof(__cvmx_pow_dump_t)) 579151497Sru { 580151497Sru 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); 581151497Sru return; 582151497Sru } 583151497Sru 584151497Sru memset(entry_list, 0, sizeof(entry_list)); 585151497Sru num_cores = cvmx_octeon_num_cores(); 586151497Sru 587151497Sru /* Print the free list info */ 588151497Sru { 589151497Sru int valid[3], has_one[3], head[3], tail[3], qnum_head, qnum_tail; 590151497Sru int idx; 591151497Sru 592151497Sru valid[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_val; 593151497Sru valid[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_val; 594151497Sru valid[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_val; 595151497Sru has_one[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_one; 596151497Sru has_one[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_one; 597151497Sru has_one[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_one; 598151497Sru head[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_head; 599151497Sru head[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_head; 600151497Sru head[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_head; 601151497Sru tail[0] = dump->sindexload[0][4].sindexload1_cn68xx.queue_tail; 602151497Sru tail[1] = dump->sindexload[0][5].sindexload1_cn68xx.queue_tail; 603151497Sru tail[2] = dump->sindexload[0][6].sindexload1_cn68xx.queue_tail; 604151497Sru qnum_head = dump->sindexload[0][4].sindexload1_cn68xx.qnum_head; 605151497Sru qnum_tail = dump->sindexload[0][4].sindexload1_cn68xx.qnum_tail; 606151497Sru 607151497Sru printf("Free List: qnum_head=%d, qnum_tail=%d\n", qnum_head, qnum_tail); 608151497Sru printf("Free0: valid=%d, one=%d, head=%llu, tail=%llu\n", valid[0], has_one[0], CAST64(head[0]), CAST64(tail[0])); 609151497Sru printf("Free1: valid=%d, one=%d, head=%llu, tail=%llu\n", valid[1], has_one[1], CAST64(head[1]), CAST64(tail[1])); 610151497Sru printf("Free2: valid=%d, one=%d, head=%llu, tail=%llu\n", valid[2], has_one[2], CAST64(head[2]), CAST64(tail[2])); 611151497Sru 612151497Sru idx=qnum_head; 613151497Sru while (valid[0] || valid[1] || valid[2]) 614151497Sru { 615151497Sru int qidx = idx % 3; 616151497Sru 617151497Sru if (head[qidx] == tail[qidx]) 618151497Sru valid[qidx] = 0; 619151497Sru 620151497Sru if (__cvmx_pow_entry_mark_list(head[qidx], CVMX_POW_LIST_FREE, entry_list)) 621151497Sru break; 622151497Sru head[qidx] = dump->smemload[head[qidx]][4].s_smemload3_cn68xx.fwd_index; 623151497Sru //printf("qidx = %d, idx = %d, head[qidx] = %d\n", qidx, idx, head[qidx]); 624151497Sru idx++; 625151497Sru } 626151497Sru } 627151497Sru 628151497Sru /* Print the core state */ 629151497Sru for (core = 0; core < num_cores; core++) 630151497Sru { 631151497Sru int pendtag = 1; 632151497Sru int pendwqp = 2; 633151497Sru int tag = 3; 634151497Sru int wqp = 4; 635151497Sru int links = 5; 636151497Sru 637151497Sru printf("Core %d State: tag=%s,0x%08x", core, 638151497Sru OCT_TAG_TYPE_STRING(dump->sstatus[core][tag].s_sstatus2_cn68xx.tag_type), 639151497Sru dump->sstatus[core][tag].s_sstatus2_cn68xx.tag); 640151497Sru if (dump->sstatus[core][tag].s_sstatus2_cn68xx.tag_type != CVMX_POW_TAG_TYPE_NULL_NULL) 641151497Sru { 642151497Sru __cvmx_pow_entry_mark_list(dump->sstatus[core][tag].s_sstatus2_cn68xx.index, CVMX_POW_LIST_CORE + core, entry_list); 643151497Sru printf(" grp=%d", dump->sstatus[core][tag].s_sstatus2_cn68xx.grp); 644151497Sru printf(" wqp=0x%016llx", CAST64(dump->sstatus[core][wqp].s_sstatus3_cn68xx.wqp)); 645151497Sru printf(" index=%d", dump->sstatus[core][tag].s_sstatus2_cn68xx.index); 646151497Sru if (dump->sstatus[core][links].s_sstatus4_cn68xx.head) 647151497Sru printf(" head"); 648151497Sru else 649151497Sru printf(" prev=%d", dump->sstatus[core][links].s_sstatus4_cn68xx.revlink_index); 650151497Sru if (dump->sstatus[core][links].s_sstatus4_cn68xx.tail) 651151497Sru printf(" tail"); 652151497Sru else 653151497Sru printf(" next=%d", dump->sstatus[core][links].s_sstatus4_cn68xx.link_index); 654151497Sru } 655151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_switch) 656151497Sru { 657151497Sru printf(" pend_switch=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_switch); 658151497Sru } 659151497Sru 660151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_desched) 661151497Sru { 662151497Sru printf(" pend_desched=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_desched); 663151497Sru printf(" pend_nosched=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_nosched); 664151497Sru } 665151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_get_work) 666151497Sru { 667151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_get_work_wait) 668151497Sru printf(" (Waiting for work)"); 669151497Sru else 670151497Sru printf(" (Getting work)"); 671151497Sru } 672151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_alloc_we) 673151497Sru printf(" pend_alloc_we=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_alloc_we); 674151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_nosched_clr) 675151497Sru { 676151497Sru printf(" pend_nosched_clr=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_nosched_clr); 677151497Sru printf(" pend_index=%d", dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_index); 678151497Sru } 679151497Sru if (dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_switch) 680151497Sru { 681151497Sru printf(" pending tag=%s,0x%08x", 682151497Sru OCT_TAG_TYPE_STRING(dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_type), 683151497Sru dump->sstatus[core][pendtag].s_sstatus0_cn68xx.pend_tag); 684151497Sru } 685151497Sru if (dump->sstatus[core][pendwqp].s_sstatus1_cn68xx.pend_nosched_clr) 686151497Sru printf(" pend_wqp=0x%016llx\n", CAST64(dump->sstatus[core][pendwqp].s_sstatus1_cn68xx.pend_wqp)); 687151497Sru printf("\n"); 688151497Sru } 689151497Sru 690151497Sru /* Print out the state of the nosched list and the 16 deschedule lists. */ 691151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_NOSCHED, dump, entry_list, 692151497Sru dump->sindexload[0][3].sindexload0_cn68xx.queue_val, 693151497Sru dump->sindexload[0][3].sindexload0_cn68xx.queue_one, 694151497Sru dump->sindexload[0][3].sindexload0_cn68xx.queue_head, 695151497Sru dump->sindexload[0][3].sindexload0_cn68xx.queue_tail); 696151497Sru for (index=0; index<64; index++) 697151497Sru { 698151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_DESCHED + index, dump, entry_list, 699151497Sru dump->sindexload[index][2].sindexload0_cn68xx.queue_val, 700151497Sru dump->sindexload[index][2].sindexload0_cn68xx.queue_one, 701151497Sru dump->sindexload[index][2].sindexload0_cn68xx.queue_head, 702151497Sru dump->sindexload[index][2].sindexload0_cn68xx.queue_tail); 703151497Sru } 704151497Sru 705151497Sru /* Print out the state of the 8 internal input queues */ 706151497Sru for (index=0; index<8; index++) 707151497Sru { 708151497Sru __cvmx_pow_display_list_and_walk(CVMX_POW_LIST_INPUT + index, dump, entry_list, 709151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_val, 710151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_one, 711151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_head, 712151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_tail); 713151497Sru } 714151497Sru 715151497Sru /* Print out the state of the 16 memory queues */ 716151497Sru for (index=0; index<8; index++) 717151497Sru { 718151497Sru const char *name; 719151497Sru if (dump->sindexload[index][1].sindexload0_cn68xx.queue_head) 720151497Sru name = "Queue %da Memory (is head)"; 721151497Sru else 722151497Sru name = "Queue %da Memory"; 723151497Sru __cvmx_pow_display_list(name, index, 724151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_val, 725151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_one, 726151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_head, 727151497Sru dump->sindexload[index][1].sindexload0_cn68xx.queue_tail); 728151497Sru if (dump->sindexload[index+8][1].sindexload0_cn68xx.queue_head) 729151497Sru name = "Queue %db Memory (is head)"; 730151497Sru else 731151497Sru name = "Queue %db Memory"; 732151497Sru __cvmx_pow_display_list(name, index, 733151497Sru dump->sindexload[index+8][1].sindexload0_cn68xx.queue_val, 734151497Sru dump->sindexload[index+8][1].sindexload0_cn68xx.queue_one, 735151497Sru dump->sindexload[index+8][1].sindexload0_cn68xx.queue_head, 736151497Sru dump->sindexload[index+8][1].sindexload0_cn68xx.queue_tail); 737151497Sru } 738151497Sru 739151497Sru /* Print out each of the internal POW entries. Each entry has a tag, group, 740151497Sru wqe, and possibly a next pointer. The next pointer is only valid if this 741151497Sru entry isn't make as a tail */ 742151497Sru for (index=0; index<num_pow_entries; index++) 743151497Sru { 744151497Sru printf("Entry %d(%-10s): tag=%s,0x%08x grp=%d wqp=0x%016llx", index, 745151497Sru __cvmx_pow_list_names[entry_list[index]], 746151497Sru OCT_TAG_TYPE_STRING(dump->smemload[index][1].s_smemload0_cn68xx.tag_type), 747151497Sru dump->smemload[index][1].s_smemload0_cn68xx.tag, 748151497Sru dump->smemload[index][2].s_smemload1_cn68xx.grp, 749151497Sru CAST64(dump->smemload[index][2].s_smemload1_cn68xx.wqp)); 750151497Sru if (dump->smemload[index][1].s_smemload0_cn68xx.tail) 751151497Sru printf(" tail"); 752151497Sru else 753151497Sru printf(" next=%d", dump->smemload[index][4].s_smemload3_cn68xx.fwd_index); 754151497Sru if (entry_list[index] >= CVMX_POW_LIST_DESCHED) 755151497Sru { 756151497Sru printf(" prev=%d", dump->smemload[index][4].s_smemload3_cn68xx.fwd_index); 757151497Sru printf(" nosched=%d", dump->smemload[index][1].s_smemload1_cn68xx.nosched); 758151497Sru if (dump->smemload[index][3].s_smemload2_cn68xx.pend_switch) 759151497Sru { 760151497Sru printf(" pending tag=%s,0x%08x", 761151497Sru OCT_TAG_TYPE_STRING(dump->smemload[index][3].s_smemload2_cn68xx.pend_type), 762151497Sru dump->smemload[index][3].s_smemload2_cn68xx.pend_tag); 763151497Sru } 764151497Sru } 765151497Sru printf("\n"); 766151497Sru } 767151497Sru} 768151497Sru 769151497Sru/** 770151497Sru * Dump a POW capture to the console in a human readable format. 771151497Sru * 772151497Sru * @param buffer POW capture from cvmx_pow_capture() 773151497Sru * @param buffer_size 774151497Sru * Size of the buffer 775151497Sru */ 776151497Sruvoid cvmx_pow_display(void *buffer, int buffer_size) 777151497Sru{ 778151497Sru printf("POW Display Start\n"); 779151497Sru 780151497Sru if (octeon_has_feature(OCTEON_FEATURE_PKND)) 781151497Sru __cvmx_pow_display_v2(buffer, buffer_size); 782151497Sru else 783151497Sru __cvmx_pow_display_v1(buffer, buffer_size); 784151497Sru 785151497Sru printf("POW Display End\n"); 786151497Sru return; 787151497Sru} 788151497Sru 789151497Sru