2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /* Copyright 2009 QLogic Corporation */
  23 
  24 /*
  25  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  26  * Use is subject to license terms.
  27  */
  28 
  29 #pragma ident   "Copyright 2009 QLogic Corporation; ql_debug.c"
  30 
  31 /*
  32  * Qlogic ISP22xx/ISP23xx/ISP24xx FCA driver source
  33  *
  34  * ***********************************************************************
  35  * *                                                                    **
  36  * *                            NOTICE                                  **
  37  * *            COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION              **
  38  * *                    ALL RIGHTS RESERVED                             **
  39  * *                                                                    **
  40  * ***********************************************************************
  41  *
  42  */
  43 
  44 #include <ql_apps.h>
  45 #include <ql_api.h>
  46 #include <ql_debug.h>
  47 
  48 static int ql_flash_errlog_store(ql_adapter_state_t *, uint32_t *);
  49 int ql_validate_trace_desc(ql_adapter_state_t *ha);
  50 char *ql_find_trace_start(ql_adapter_state_t *ha);
  51 
  52 /*
  53  * Global Data.
  54  */
  55 uint32_t        el_message_number = 0;
  56 uint32_t        ql_enable_ellock = 0;
  57 
  58 extern int      getpcstack(pc_t *, int);
  59 extern char     *kobj_getsymname(uintptr_t, ulong_t *);
  60 
  61 /*
  62  * ql_dump_buffer
  63  *       Outputs buffer.
  64  *
  65  * Input:
  66  *       string:        Null terminated string (no newline at end).
  67  *       buffer:        buffer address.
  68  *       wd_size:       word size 8 bits
  69  *       count:         number of words.
  70  */
 
 
 129                 cmn_err(CE_CONT, "%s\n", str);
 130         }
 131 }
 132 
 133 /*
 134  * ql_el_msg
 135  *      Extended logging message
 136  *
 137  * Input:
 138  *      ha:     adapter state pointer.
 139  *      fn:     function name.
 140  *      ce:     level
 141  *      ...:    Variable argument list.
 142  *
 143  * Context:
 144  *      Kernel/Interrupt context.
 145  */
 146 void
 147 ql_el_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...)
 148 {
 149         uint32_t        el_msg_num;
 150         char            *s, *fmt = 0, *fmt1 = 0;
 151         char            fmt2[256];
 152         int             rval, tmp;
 153         int             tracing = 0;
 154         va_list         vl;
 155 
 156         /* Tracing is the default but it can be disabled. */
 157         if ((CFG_IST(ha, CFG_DISABLE_EXTENDED_LOGGING_TRACE) == 0) &&
 158             (rval = ql_validate_trace_desc(ha) == DDI_SUCCESS)) {
 159                 tracing = 1;
 160 
 161                 TRACE_BUFFER_LOCK(ha);
 162 
 163                 /*
 164                  * Ensure enough space for the string. Wrap to
 165                  * start when default message allocation size
 166                  * would overrun the end.
 167                  */
 168                 if ((ha->el_trace_desc->next + EL_BUFFER_RESERVE) >=
 169                     ha->el_trace_desc->trace_buffer_size) {
 170                         fmt = ha->el_trace_desc->trace_buffer;
 171                         ha->el_trace_desc->next = 0;
 172                 } else {
 173                         fmt = ha->el_trace_desc->trace_buffer +
 174                             ha->el_trace_desc->next;
 175                 }
 176         }
 177         /* if no buffer use the stack */
 178         if (fmt == NULL) {
 179                 fmt = fmt2;
 180         }
 181 
 182         va_start(vl, ce);
 183 
 184         s = va_arg(vl, char *);
 185 
 186         if (ql_enable_ellock) {
 187                 /*
 188                  * Used when messages are *maybe* being lost.  Adds
 189                  * a unique number to the message so one can see if
 190                  * any messages have been dropped. NB: This slows
 191                  * down the driver, which may make the issue disappear.
 192                  */
 193                 GLOBAL_EL_LOCK();
 194                 el_msg_num = ++el_message_number;
 195                 GLOBAL_EL_UNLOCK();
 196 
 197                 rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
 198                     QL_BANG "QEL%d %s(%d,%d): %s, ", el_msg_num, QL_NAME,
 199                     ha->instance, ha->vp_index, fn);
 200                 fmt1 = fmt + rval;
 201                 tmp = (int)vsnprintf(fmt1,
 202                     (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
 203                 rval += tmp;
 204         } else {
 205                 rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
 206                     QL_BANG "QEL %s(%d,%d): %s, ", QL_NAME, ha->instance,
 207                     ha->vp_index, fn);
 208                 fmt1 = fmt + rval;
 209                 tmp = (int)vsnprintf(fmt1,
 210                     (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
 211                 rval += tmp;
 212         }
 213 
 214         /*
 215          * Calculate the offset where the next message will go,
 216          * skipping the NULL.
 217          */
 218         if (tracing) {
 219                 uint16_t next = (uint16_t)(rval += 1);
 220                 ha->el_trace_desc->next += next;
 221                 TRACE_BUFFER_UNLOCK(ha);
 222         }
 223 
 224         if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) {
 225                 cmn_err(ce, fmt);
 226         }
 227 
 228         va_end(vl);
 229 }
 230 
 231 /*
 232  * ql_el_msg
 233  *      Extended logging message
 234  *
 235  * Input:
 236  *      ha:     adapter state pointer.
 237  *      fn:     function name.
 238  *      ce:     level
 239  *      ...:    Variable argument list.
 240  *
 241  * Context:
 242  *      Kernel/Interrupt context.
 243  */
 244 void
 245 ql_dbg_msg(const char *fn, int ce, ...)
 246 {
 247         uint32_t        el_msg_num;
 248         char            *s;
 249         char            fmt[256];
 250         va_list         vl;
 251 
 252         va_start(vl, ce);
 253 
 254         s = va_arg(vl, char *);
 255 
 256         if (ql_enable_ellock) {
 257                 /*
 258                  * Used when messages are *maybe* being lost.  Adds
 259                  * a unique number to the message to one can see if
 260                  * any messages have been dropped. NB: This slows
 261                  * down the driver, which may make the issue disappear.
 262                  */
 263                 GLOBAL_EL_LOCK();
 264                 el_msg_num = ++el_message_number;
 265                 GLOBAL_EL_UNLOCK();
 266                 (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s %s, %s",
 267                     el_msg_num, QL_NAME, fn, s);
 268         } else {
 269                 (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s %s, %s",
 270                     QL_NAME, fn, s);
 271         }
 272 
 273         vcmn_err(ce, fmt, vl);
 274 
 275         va_end(vl);
 276 }
 277 
 278 /*
 279  * ql_stacktrace
 280  *      Prints out current stack
 281  *
 282  * Input:
 283  *      ha:     adapter state pointer.
 284  *
 285  * Context:
 286  *      Kernel/Interrupt context.
 287  */
 288 void
 289 ql_stacktrace(ql_adapter_state_t *ha)
 290 {
 291         int     depth, i;
 
 321  *
 322  * Input:
 323  *      ha:     adapter state pointer.
 324  *      code:   Error code
 325  *      d1-d3:  Error code data
 326  *
 327  * Returns:
 328  *      ql local function return status code.
 329  *
 330  * Context:
 331  *      Kernel/Interrupt context.
 332  */
 333 int
 334 ql_flash_errlog(ql_adapter_state_t *ha, uint16_t code, uint16_t d1,
 335     uint16_t d2, uint16_t d3)
 336 {
 337         char            *s;
 338         uint32_t        marker[2], fdata[2], faddr;
 339         int             rval;
 340 
 341         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 342 
 343         if (ha->flash_errlog_start == 0) {
 344                 return (QL_NOT_SUPPORTED);
 345         }
 346 
 347         EL(ha, "code=%xh, d1=%xh, d2=%xh, d3=%xh\n", code, d1, d2, d3);
 348 
 349         /*
 350          * If marker not already found, locate or write marker.
 351          */
 352         if (!(ha->flags & FLASH_ERRLOG_MARKER)) {
 353 
 354                 /* Create marker. */
 355                 marker[0] = CHAR_TO_LONG(ha->fw_subminor_version,
 356                     ha->fw_minor_version, ha->fw_major_version, 'S');
 357 
 358                 /*
 359                  * Version should be of the format: YYYYMMDD-v.vv
 360                  */
 361                 if ((strlen(QL_VERSION) > 9) && (QL_VERSION[8] == '-')) {
 
 400                 if (!(ha->flags & FLASH_ERRLOG_MARKER)) {
 401                         ha->flags |= FLASH_ERRLOG_MARKER;
 402                         rval = ql_flash_errlog_store(ha, marker);
 403                         if (rval != QL_SUCCESS) {
 404                                 EL(ha, "failed marker write=%xh\n", rval);
 405                                 return (rval);
 406                         }
 407                 }
 408         }
 409 
 410         /*
 411          * Store error.
 412          */
 413         fdata[0] = SHORT_TO_LONG(d1, code);
 414         fdata[1] = SHORT_TO_LONG(d3, d2);
 415         rval = ql_flash_errlog_store(ha, fdata);
 416         if (rval != QL_SUCCESS) {
 417                 EL(ha, "failed error write=%xh\n", rval);
 418         } else {
 419                 /*EMPTY*/
 420                 QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 421         }
 422 
 423         return (rval);
 424 }
 425 
 426 /*
 427  * ql_flash_errlog_store
 428  *      Stores error to flash.
 429  *      Entry Layout:
 430  *              uint32_t TimeStamp;
 431  *              uint16_t CodeData[4];
 432  *
 433  * Input:
 434  *      ha:                     adapter state pointer.
 435  *      fdata:                  Error code plus data.
 436  *      ha->flash_errlog_ptr:        Current Flash error pointer.
 437  *
 438  * Output:
 439  *      ha->flash_errlog_ptr:        updated pointer.
 440  *
 441  * Returns:
 442  *      ql local function return status code.
 443  *
 444  * Context:
 445  *      Kernel/Interrupt context.
 446  */
 447 static int
 448 ql_flash_errlog_store(ql_adapter_state_t *ha, uint32_t *fdata)
 449 {
 450         int             rval;
 451         uint64_t        time;
 452         uint32_t        d1, d2, faddr;
 453 
 454         QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
 455 
 456         /* Locate first empty entry */
 457         for (;;) {
 458                 if (ha->flash_errlog_ptr >=
 459                     ha->flash_errlog_start + FLASH_ERRLOG_SIZE) {
 460                         EL(ha, "log full\n");
 461                         return (QL_MEMORY_FULL);
 462                 }
 463 
 464                 faddr = ha->flash_data_addr | ha->flash_errlog_ptr;
 465                 ha->flash_errlog_ptr += FLASH_ERRLOG_ENTRY_SIZE;
 466                 (void) ql_24xx_read_flash(ha, faddr, &d1);
 467                 (void) ql_24xx_read_flash(ha, faddr + 1, &d2);
 468                 if (d1 == 0xffffffff && d2 == 0xffffffff) {
 469                         (void) drv_getparm(TIME, &time);
 470 
 471                         /* Enable flash write. */
 472                         if ((rval = ql_24xx_unprotect_flash(ha)) !=
 473                             QL_SUCCESS) {
 474                                 EL(ha, "unprotect_flash failed, rval=%xh\n",
 475                                     rval);
 476                                 return (rval);
 477                         }
 478 
 479                         (void) ql_24xx_write_flash(ha, faddr++, LSD(time));
 480                         (void) ql_24xx_write_flash(ha, faddr++, MSD(time));
 481                         (void) ql_24xx_write_flash(ha, faddr++, *fdata++);
 482                         (void) ql_24xx_write_flash(ha, faddr++, *fdata);
 483 
 484                         /* Enable flash write-protection. */
 485                         ql_24xx_protect_flash(ha);
 486                         break;
 487                 }
 488         }
 489 
 490         QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
 491 
 492         return (QL_SUCCESS);
 493 }
 494 
 495 /*
 496  * ql_dump_el_trace_buffer
 497  *       Outputs extended logging trace buffer.
 498  *
 499  * Input:
 500  *      ha:     adapter state pointer.
 501  */
 502 void
 503 ql_dump_el_trace_buffer(ql_adapter_state_t *ha)
 504 {
 505         char            *dump_start = NULL;
 506         char            *dump_current = NULL;
 507         char            *trace_start;
 508         char            *trace_end;
 509         int             wrapped = 0;
 510         int             rval;
 511 
 512         TRACE_BUFFER_LOCK(ha);
 513 
 514         rval = ql_validate_trace_desc(ha);
 515         if (rval != NULL) {
 516                 cmn_err(CE_CONT, "%s(%d) Dump EL trace - invalid desc\n",
 517                     QL_NAME, ha->instance);
 518         } else if ((dump_start = ql_find_trace_start(ha)) != NULL) {
 519                 dump_current = dump_start;
 520                 trace_start = ha->el_trace_desc->trace_buffer;
 521                 trace_end = trace_start +
 522                     ha->el_trace_desc->trace_buffer_size;
 523 
 524                 cmn_err(CE_CONT, "%s(%d) Dump EL trace - start %p %p\n",
 525                     QL_NAME, ha->instance,
 526                     (void *)dump_start, (void *)trace_start);
 527 
 528                 while (((uintptr_t)dump_current - (uintptr_t)trace_start) <=
 529                     (uintptr_t)ha->el_trace_desc->trace_buffer_size) {
 530                         /* Show it... */
 531                         cmn_err(CE_CONT, "%p - %s", (void *)dump_current,
 532                             dump_current);
 533                         /* Make the next the current */
 534                         dump_current += (strlen(dump_current) + 1);
 535                         /* check for wrap */
 536                         if ((dump_current + EL_BUFFER_RESERVE) >= trace_end) {
 537                                 dump_current = trace_start;
 538                                 wrapped = 1;
 539                         } else if (wrapped) {
 540                                 /* Don't go past next. */
 541                                 if ((trace_start + ha->el_trace_desc->next) <=
 542                                     dump_current) {
 543                                         break;
 544                                 }
 545                         } else if (*dump_current == NULL) {
 546                                 break;
 547                         }
 548                 }
 549         }
 550         TRACE_BUFFER_UNLOCK(ha);
 551 }
 552 
 553 /*
 554  * ql_validate_trace_desc
 555  *       Ensures the extended logging trace descriptor is good
 556  *
 557  * Input:
 558  *      ha:     adapter state pointer.
 559  *
 560  * Returns:
 561  *      ql local function return status code.
 562  */
 563 int
 564 ql_validate_trace_desc(ql_adapter_state_t *ha)
 565 {
 566         int     rval = DDI_SUCCESS;
 567 
 568         if (ha->el_trace_desc == NULL) {
 569                 rval = DDI_FAILURE;
 570         } else if (ha->el_trace_desc->trace_buffer == NULL) {
 571                 rval = DDI_FAILURE;
 572         }
 573         return (rval);
 574 }
 575 
 576 /*
 577  * ql_find_trace_start
 578  *       Locate the oldest extended logging trace entry.
 579  *
 580  * Input:
 581  *      ha:     adapter state pointer.
 582  *
 583  * Returns:
 584  *      Pointer to a string.
 585  *
 586  * Context:
 587  *      Kernel/Interrupt context.
 588  */
 589 char *
 590 ql_find_trace_start(ql_adapter_state_t *ha)
 591 {
 592         char    *trace_start = 0;
 593         char    *trace_next  = 0;
 594 
 595         trace_next = ha->el_trace_desc->trace_buffer + ha->el_trace_desc->next;
 596 
 597         /*
 598          * if the buffer has not wrapped next will point at a null so
 599          * start is the beginning of the buffer.  if next points at a char
 600          * then we must traverse the buffer until a null is detected and
 601          * that will be the beginning of the oldest whole object in the buffer
 602          * which is the start.
 603          */
 604 
 605         if ((trace_next + EL_BUFFER_RESERVE) >=
 606             (ha->el_trace_desc->trace_buffer +
 607             ha->el_trace_desc->trace_buffer_size)) {
 608                 trace_start = ha->el_trace_desc->trace_buffer;
 609         } else if (*trace_next != NULL) {
 610                 trace_start = trace_next + (strlen(trace_next) + 1);
 611         } else {
 612                 trace_start = ha->el_trace_desc->trace_buffer;
 613         }
 614         return (trace_start);
 615 }
 | 
 
 
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /* Copyright 2015 QLogic Corporation */
  23 
  24 /*
  25  * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
  26  */
  27 
  28 #pragma ident   "Copyright 2015 QLogic Corporation; ql_debug.c"
  29 
  30 /*
  31  * Qlogic ISP22xx/ISP23xx/ISP24xx FCA driver source
  32  *
  33  * ***********************************************************************
  34  * *                                                                    **
  35  * *                            NOTICE                                  **
  36  * *            COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION              **
  37  * *                    ALL RIGHTS RESERVED                             **
  38  * *                                                                    **
  39  * ***********************************************************************
  40  *
  41  */
  42 
  43 #include <ql_apps.h>
  44 #include <ql_api.h>
  45 #include <ql_debug.h>
  46 
  47 static int ql_flash_errlog_store(ql_adapter_state_t *, uint32_t *);
  48 
  49 /*
  50  * Global Data.
  51  */
  52 uint32_t        el_message_number = 0;
  53 uint32_t        ql_enable_ellock = 0;
  54 
  55 extern int      getpcstack(pc_t *, int);
  56 extern char     *kobj_getsymname(uintptr_t, ulong_t *);
  57 
  58 /*
  59  * ql_dump_buffer
  60  *       Outputs buffer.
  61  *
  62  * Input:
  63  *       string:        Null terminated string (no newline at end).
  64  *       buffer:        buffer address.
  65  *       wd_size:       word size 8 bits
  66  *       count:         number of words.
  67  */
 
 
 126                 cmn_err(CE_CONT, "%s\n", str);
 127         }
 128 }
 129 
 130 /*
 131  * ql_el_msg
 132  *      Extended logging message
 133  *
 134  * Input:
 135  *      ha:     adapter state pointer.
 136  *      fn:     function name.
 137  *      ce:     level
 138  *      ...:    Variable argument list.
 139  *
 140  * Context:
 141  *      Kernel/Interrupt context.
 142  */
 143 void
 144 ql_el_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...)
 145 {
 146         char            *s, *fmt, *fmt1;
 147         /*
 148          * EL_BUFFER_RESERVE 256 is the max # of bytes
 149          * that driver's log could be collected.
 150          * add 3 more buytes for safely maniplulation.
 151          */
 152         char                    buf[EL_BUFFER_RESERVE + 3];
 153         char                    buf1[QL_LOG_LENGTH];
 154         size_t                  tmp, rval, rval1, left;
 155         va_list                 vl;
 156         ql_trace_desc_t         *desc;
 157         ql_trace_entry_t        *entry;
 158         uint32_t                cindex, count;
 159         timespec_t              time;
 160 
 161         if (ha == NULL && (ha = ql_hba.first->base_address) == NULL) {
 162                 return;
 163         }
 164 
 165         desc = ha->ql_trace_desc;
 166 
 167         (void) bzero((void *)&buf[0], EL_BUFFER_RESERVE + 3);
 168         fmt1 = &buf[0];
 169 
 170         TRACE_BUFFER_LOCK(ha);
 171 
 172         /* locate the entry to be filled out */
 173         cindex = desc->nindex;
 174         entry = &desc->trace_buffer[cindex];
 175 
 176         count = desc->count;
 177 
 178         desc->end = desc->nindex;
 179         desc->nindex++;
 180 
 181         if (desc->nindex == desc->nentries) {
 182                 desc->nindex = 0;
 183         }
 184 
 185         if (desc->csize < desc->nentries) {
 186                 desc->csize++;
 187         } else {
 188                 /*
 189                  * once wrapped, csize is fixed.
 190                  * so we have to adjust start point
 191                  */
 192                 desc->start = desc->nindex;
 193         }
 194 
 195         gethrestime(&time);
 196 
 197         rval = snprintf(fmt1, (size_t)EL_BUFFER_RESERVE,
 198             QL_BANG "%d=>QEL %s(%d,%d,%d):: %s, ", count, QL_NAME,
 199             ha->instance, ha->vp_index, ha->pci_function_number, fn);
 200 
 201         rval1 = rval;
 202 
 203         va_start(vl, ce);
 204         s = va_arg(vl, char *);
 205 
 206         fmt = fmt1 + rval;
 207 
 208         tmp = vsnprintf(fmt,
 209             (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
 210 
 211         va_end(vl);
 212 
 213         rval += tmp;
 214 
 215         if (rval > QL_LOG_LENGTH - 1) {
 216                 left = rval - (QL_LOG_LENGTH - 1);
 217 
 218                 /* store the remaining string */
 219                 (void) strncpy(buf1, fmt1 + (QL_LOG_LENGTH - 1), left);
 220 
 221                 (void) strncpy(entry->buf, fmt1, (QL_LOG_LENGTH - 1));
 222                 entry->buf[QL_LOG_LENGTH - 1] = '\n';
 223 
 224                 bcopy((void *)&time, (void *)&entry->hs_time,
 225                     sizeof (timespec_t));
 226 
 227                 /*
 228                  * remaining msg will be stored in the nex entry
 229                  * with same timestamp and same sequence number
 230                  */
 231                 cindex = desc->nindex;
 232                 entry = &desc->trace_buffer[cindex];
 233 
 234                 desc->end = desc->nindex;
 235                 desc->nindex++;
 236 
 237                 if (desc->nindex == desc->nentries) {
 238                         desc->nindex = 0;
 239                 }
 240 
 241                 if (desc->csize < desc->nentries) {
 242                         desc->csize++;
 243                 } else {
 244                         desc->start = desc->nindex;
 245                 }
 246 
 247                 (void) strncpy(&entry->buf[0], fmt1, rval1);
 248                 (void) strncpy(&entry->buf[rval1], &buf1[0], left);
 249                 entry->buf[rval1 + left] = 0;
 250 
 251                 bcopy((void *)&time, (void *)&entry->hs_time,
 252                     sizeof (timespec_t));
 253 
 254                 if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) {
 255                         cmn_err(ce, fmt1);
 256                 }
 257 
 258                 desc->count++;
 259 
 260                 TRACE_BUFFER_UNLOCK(ha);
 261                 return;
 262         }
 263 
 264         desc->count++;
 265         bcopy((void *)&time, (void *)&entry->hs_time,
 266             sizeof (timespec_t));
 267 
 268         (void) strncpy(entry->buf, fmt1, sizeof (entry->buf));
 269         entry->buf[rval] = 0;
 270 
 271         TRACE_BUFFER_UNLOCK(ha);
 272 
 273         if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) {
 274                 cmn_err(ce, fmt1);
 275         }
 276 }
 277 
 278 /*
 279  * ql_dbg_msg
 280  *      Extended logging message
 281  *
 282  * Input:
 283  *      ha:     adapter state pointer.
 284  *      fn:     function name.
 285  *      ce:     level
 286  *      ...:    Variable argument list.
 287  *
 288  * Context:
 289  *      Kernel/Interrupt context.
 290  */
 291 void
 292 ql_dbg_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...)
 293 {
 294         uint32_t        el_msg_num;
 295         char            *s;
 296         char            fmt[EL_BUFFER_RESERVE];
 297         va_list         vl;
 298 
 299         va_start(vl, ce);
 300 
 301         s = va_arg(vl, char *);
 302 
 303         if (ql_enable_ellock) {
 304                 /*
 305                  * Used when messages are *maybe* being lost.  Adds
 306                  * a unique number to the message to one can see if
 307                  * any messages have been dropped. NB: This slows
 308                  * down the driver, which may make the issue disappear.
 309                  */
 310                 GLOBAL_EL_LOCK();
 311                 el_msg_num = ++el_message_number;
 312                 GLOBAL_EL_UNLOCK();
 313                 if (ha == NULL) {
 314                         (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s, "
 315                             "%s", el_msg_num, fn, s);
 316                 } else {
 317                         (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s"
 318                             "(%d,%d,%d): %s", el_msg_num, fn, ha->instance,
 319                             ha->vp_index, ha->pci_function_number, s);
 320                 }
 321         } else {
 322                 if (ha == NULL) {
 323                         (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s, "
 324                             "%s", fn, s);
 325                 } else {
 326                         (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s"
 327                             "(%d,%d,%d): %s", fn, ha->instance, ha->vp_index,
 328                             ha->pci_function_number, s);
 329                 }
 330         }
 331 
 332         vcmn_err(ce, fmt, vl);
 333 
 334         va_end(vl);
 335 }
 336 
 337 /*
 338  * ql_stacktrace
 339  *      Prints out current stack
 340  *
 341  * Input:
 342  *      ha:     adapter state pointer.
 343  *
 344  * Context:
 345  *      Kernel/Interrupt context.
 346  */
 347 void
 348 ql_stacktrace(ql_adapter_state_t *ha)
 349 {
 350         int     depth, i;
 
 380  *
 381  * Input:
 382  *      ha:     adapter state pointer.
 383  *      code:   Error code
 384  *      d1-d3:  Error code data
 385  *
 386  * Returns:
 387  *      ql local function return status code.
 388  *
 389  * Context:
 390  *      Kernel/Interrupt context.
 391  */
 392 int
 393 ql_flash_errlog(ql_adapter_state_t *ha, uint16_t code, uint16_t d1,
 394     uint16_t d2, uint16_t d3)
 395 {
 396         char            *s;
 397         uint32_t        marker[2], fdata[2], faddr;
 398         int             rval;
 399 
 400         QL_PRINT_3(ha, "started\n");
 401 
 402         if (ha->flash_errlog_start == 0) {
 403                 return (QL_NOT_SUPPORTED);
 404         }
 405 
 406         EL(ha, "code=%xh, d1=%xh, d2=%xh, d3=%xh\n", code, d1, d2, d3);
 407 
 408         /*
 409          * If marker not already found, locate or write marker.
 410          */
 411         if (!(ha->flags & FLASH_ERRLOG_MARKER)) {
 412 
 413                 /* Create marker. */
 414                 marker[0] = CHAR_TO_LONG(ha->fw_subminor_version,
 415                     ha->fw_minor_version, ha->fw_major_version, 'S');
 416 
 417                 /*
 418                  * Version should be of the format: YYYYMMDD-v.vv
 419                  */
 420                 if ((strlen(QL_VERSION) > 9) && (QL_VERSION[8] == '-')) {
 
 459                 if (!(ha->flags & FLASH_ERRLOG_MARKER)) {
 460                         ha->flags |= FLASH_ERRLOG_MARKER;
 461                         rval = ql_flash_errlog_store(ha, marker);
 462                         if (rval != QL_SUCCESS) {
 463                                 EL(ha, "failed marker write=%xh\n", rval);
 464                                 return (rval);
 465                         }
 466                 }
 467         }
 468 
 469         /*
 470          * Store error.
 471          */
 472         fdata[0] = SHORT_TO_LONG(d1, code);
 473         fdata[1] = SHORT_TO_LONG(d3, d2);
 474         rval = ql_flash_errlog_store(ha, fdata);
 475         if (rval != QL_SUCCESS) {
 476                 EL(ha, "failed error write=%xh\n", rval);
 477         } else {
 478                 /*EMPTY*/
 479                 QL_PRINT_3(ha, "done\n");
 480         }
 481 
 482         return (rval);
 483 }
 484 
 485 /*
 486  * ql_flash_errlog_store
 487  *      Stores error to flash.
 488  *      Entry Layout:
 489  *              uint32_t TimeStamp;
 490  *              uint16_t CodeData[4];
 491  *
 492  * Input:
 493  *      ha:                     adapter state pointer.
 494  *      fdata:                  Error code plus data.
 495  *      ha->flash_errlog_ptr:        Current Flash error pointer.
 496  *
 497  * Output:
 498  *      ha->flash_errlog_ptr:        updated pointer.
 499  *
 500  * Returns:
 501  *      ql local function return status code.
 502  *
 503  * Context:
 504  *      Kernel/Interrupt context.
 505  */
 506 static int
 507 ql_flash_errlog_store(ql_adapter_state_t *ha, uint32_t *fdata)
 508 {
 509         int             rval;
 510         uint64_t        time;
 511         uint32_t        d1, d2, faddr;
 512 
 513         QL_PRINT_3(ha, "started\n");
 514 
 515         /* Locate first empty entry */
 516         for (;;) {
 517                 if (ha->flash_errlog_ptr >=
 518                     ha->flash_errlog_start + FLASH_ERRLOG_SIZE) {
 519                         EL(ha, "log full\n");
 520                         return (QL_MEMORY_FULL);
 521                 }
 522 
 523                 faddr = ha->flash_data_addr | ha->flash_errlog_ptr;
 524                 ha->flash_errlog_ptr += FLASH_ERRLOG_ENTRY_SIZE;
 525                 (void) ql_24xx_read_flash(ha, faddr, &d1);
 526                 (void) ql_24xx_read_flash(ha, faddr + 1, &d2);
 527                 if (d1 == 0xffffffff && d2 == 0xffffffff) {
 528                         (void) drv_getparm(TIME, &time);
 529 
 530                         /* Enable flash write. */
 531                         if ((rval = ql_24xx_unprotect_flash(ha)) !=
 532                             QL_SUCCESS) {
 533                                 EL(ha, "unprotect_flash failed, rval=%xh\n",
 534                                     rval);
 535                                 return (rval);
 536                         }
 537 
 538                         (void) ql_24xx_write_flash(ha, faddr++, LSD(time));
 539                         (void) ql_24xx_write_flash(ha, faddr++, MSD(time));
 540                         (void) ql_24xx_write_flash(ha, faddr++, *fdata++);
 541                         (void) ql_24xx_write_flash(ha, faddr++, *fdata);
 542 
 543                         /* Enable flash write-protection. */
 544                         ql_24xx_protect_flash(ha);
 545                         break;
 546                 }
 547         }
 548 
 549         QL_PRINT_3(ha, "done\n");
 550 
 551         return (QL_SUCCESS);
 552 }
 |