fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER START
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * The contents of this file are subject to the terms of the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Common Development and Distribution License (the "License").
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You may not use this file except in compliance with the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * See the License for the specific language governing permissions
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * and limitations under the License.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If applicable, add the following below this CDDL HEADER, with the
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * CDDL HEADER END
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard/* Copyright 2009 QLogic Corporation */
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Use is subject to license terms.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard#pragma ident "Copyright 2009 QLogic Corporation; ql_debug.c"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Qlogic ISP22xx/ISP23xx/ISP24xx FCA driver source
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ***********************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * * NOTICE **
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * * COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION **
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * * ALL RIGHTS RESERVED **
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ***********************************************************************
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Fortestatic int ql_flash_errlog_store(ql_adapter_state_t *, uint32_t *);
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregardint ql_validate_trace_desc(ql_adapter_state_t *ha);
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregardchar *ql_find_trace_start(ql_adapter_state_t *ha);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Global Data.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteextern char *kobj_getsymname(uintptr_t, ulong_t *);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ql_dump_buffer
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Outputs buffer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * string: Null terminated string (no newline at end).
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * buffer: buffer address.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * wd_size: word size 8 bits
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * count: number of words.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteql_dump_buffer(uint8_t *b8, uint8_t wd_size, uint32_t count)
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_CONT, "----------------------------------------\n");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_CONT, "------------------------------------------"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "------\n");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "A B C D E F\n");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_CONT, "---------------------------------"
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte "-------------------------------\n");
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Extended logging message
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ha: adapter state pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fn: function name.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ...: Variable argument list.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteql_el_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...)
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard /* Tracing is the default but it can be disabled. */
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard if ((CFG_IST(ha, CFG_DISABLE_EXTENDED_LOGGING_TRACE) == 0) &&
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard (rval = ql_validate_trace_desc(ha) == DDI_SUCCESS)) {
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Ensure enough space for the string. Wrap to
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * start when default message allocation size
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * would overrun the end.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard if ((ha->el_trace_desc->next + EL_BUFFER_RESERVE) >=
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard /* if no buffer use the stack */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Used when messages are *maybe* being lost. Adds
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * a unique number to the message so one can see if
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * any messages have been dropped. NB: This slows
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * down the driver, which may make the issue disappear.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard QL_BANG "QEL%d %s(%d,%d): %s, ", el_msg_num, QL_NAME,
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard QL_BANG "QEL %s(%d,%d): %s, ", QL_NAME, ha->instance,
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Calculate the offset where the next message will go,
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * skipping the NULL.
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) {
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Extended logging message
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ha: adapter state pointer.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * fn: function name.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ...: Variable argument list.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Used when messages are *maybe* being lost. Adds
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * a unique number to the message to one can see if
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * any messages have been dropped. NB: This slows
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * down the driver, which may make the issue disappear.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s %s, %s",
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s %s, %s",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ql_stacktrace
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Prints out current stack
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ha: adapter state pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte depth = getpcstack(&pcstack[0], DEBUG_STK_DEPTH);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_CONT, "%s(%d,%d): ---------- \n", QL_NAME, ha->instance,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte for (i = 0; i < MIN(depth, DEBUG_STK_DEPTH); i++) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte sym = kobj_getsymname((uintptr_t)pcstack[i], &off);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_CONT, "%s(%d,%d): sym is NULL\n", QL_NAME,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ha->instance, ha->vp_index, sym ? sym : "?", off);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte cmn_err(CE_CONT, "%s(%d,%d): ---------- \n", QL_NAME, ha->instance,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ql_flash_errlog
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Adds error to flash error log.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Entry Layout:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * uint32_t TimeStamp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * uint16_t CodeData[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ha: adapter state pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * code: Error code
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * d1-d3: Error code data
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ql local function return status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteql_flash_errlog(ql_adapter_state_t *ha, uint16_t code, uint16_t d1,
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte EL(ha, "code=%xh, d1=%xh, d2=%xh, d3=%xh\n", code, d1, d2, d3);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * If marker not already found, locate or write marker.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Create marker. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte marker[0] = CHAR_TO_LONG(ha->fw_subminor_version,
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte ha->fw_minor_version, ha->fw_major_version, 'S');
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Version should be of the format: YYYYMMDD-v.vv
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if ((strlen(QL_VERSION) > 9) && (QL_VERSION[8] == '-')) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte } else if (*s != '.') {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Locate marker. */
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard faddr = ha->flash_data_addr | ha->flash_errlog_ptr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_read_flash(ha, faddr++, &fdata[0]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_read_flash(ha, faddr++, &fdata[1]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fdata[0] == 0xffffffff && fdata[1] == 0xffffffff) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_read_flash(ha, faddr++, &fdata[0]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_read_flash(ha, faddr++, &fdata[1]);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte if (fdata[0] == marker[0] && fdata[1] == marker[1]) {
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* No marker, write it. */
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Store error.
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ql_flash_errlog_store
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Stores error to flash.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * Entry Layout:
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * uint32_t TimeStamp;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * uint16_t CodeData[4];
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ha: adapter state pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * fdata: Error code plus data.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ha->flash_errlog_ptr: Current Flash error pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ha->flash_errlog_ptr: updated pointer.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte * ql local function return status code.
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forteql_flash_errlog_store(ql_adapter_state_t *ha, uint32_t *fdata)
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Locate first empty entry */
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard faddr = ha->flash_data_addr | ha->flash_errlog_ptr;
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Enable flash write. */
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard if ((rval = ql_24xx_unprotect_flash(ha)) !=
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard EL(ha, "unprotect_flash failed, rval=%xh\n",
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_write_flash(ha, faddr++, LSD(time));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_write_flash(ha, faddr++, MSD(time));
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte (void) ql_24xx_write_flash(ha, faddr++, *fdata++);
fcf3ce441efd61da9bb2884968af01cb7c1452ccJohn Forte /* Enable flash write-protection. */
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ql_dump_el_trace_buffer
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Outputs extended logging trace buffer.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ha: adapter state pointer.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregardql_dump_el_trace_buffer(ql_adapter_state_t *ha)
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard cmn_err(CE_CONT, "%s(%d) Dump EL trace - invalid desc\n",
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard } else if ((dump_start = ql_find_trace_start(ha)) != NULL) {
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard trace_start = ha->el_trace_desc->trace_buffer;
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard cmn_err(CE_CONT, "%s(%d) Dump EL trace - start %p %p\n",
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard while (((uintptr_t)dump_current - (uintptr_t)trace_start) <=
5dfd244acc8f144280c5bc8f69ed941185fc3cccDaniel Beauregard (uintptr_t)ha->el_trace_desc->trace_buffer_size) {
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard /* Show it... */
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard cmn_err(CE_CONT, "%p - %s", (void *)dump_current,
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard /* Make the next the current */
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard dump_current += (strlen(dump_current) + 1);
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard /* check for wrap */
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard if ((dump_current + EL_BUFFER_RESERVE) >= trace_end) {
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard /* Don't go past next. */
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard if ((trace_start + ha->el_trace_desc->next) <=
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ql_validate_trace_desc
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Ensures the extended logging trace descriptor is good
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ha: adapter state pointer.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ql local function return status code.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregardql_validate_trace_desc(ql_adapter_state_t *ha)
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard } else if (ha->el_trace_desc->trace_buffer == NULL) {
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ql_find_trace_start
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Locate the oldest extended logging trace entry.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * ha: adapter state pointer.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * Pointer to a string.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregardql_find_trace_start(ql_adapter_state_t *ha)
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard trace_next = ha->el_trace_desc->trace_buffer + ha->el_trace_desc->next;
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * if the buffer has not wrapped next will point at a null so
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * start is the beginning of the buffer. if next points at a char
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * then we must traverse the buffer until a null is detected and
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * that will be the beginning of the oldest whole object in the buffer
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard * which is the start.
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard trace_start = ha->el_trace_desc->trace_buffer;
16dd44c265271a75647fb0bb41109bb7c585a526Daniel Beauregard trace_start = trace_next + (strlen(trace_next) + 1);