1 /* 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 /* 29 * Qlogic ISP22xx/ISP23xx/ISP24xx FCA driver source 30 * 31 * *********************************************************************** 32 * * ** 33 * * NOTICE ** 34 * * COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION ** 35 * * ALL RIGHTS RESERVED ** 36 * * ** 37 * *********************************************************************** 38 * 39 */ 40 41 #include <ql_apps.h> 42 #include <ql_api.h> 43 #include <ql_debug.h> 44 45 static int ql_flash_errlog_store(ql_adapter_state_t *, uint32_t *); 46 47 /* 48 * Global Data. 49 */ 50 uint32_t el_message_number = 0; 51 uint32_t ql_enable_ellock = 0; 52 53 extern int getpcstack(pc_t *, int); 54 extern char *kobj_getsymname(uintptr_t, ulong_t *); 55 56 /* 57 * ql_dump_buffer 58 * Outputs buffer. 59 * 60 * Input: 61 * string: Null terminated string (no newline at end). 62 * buffer: buffer address. 63 * wd_size: word size 8 bits 64 * count: number of words. 65 */ 66 void 67 ql_dump_buffer(uint8_t *b8, uint8_t wd_size, uint32_t count) 68 { 69 uint32_t cnt; 70 char str[256], *sp; 71 uint32_t *b32 = (uint32_t *)b8; 72 uint16_t *b16 = (uint16_t *)b8; 73 74 sp = &str[0]; 75 76 switch (wd_size) { 77 case 32: 78 cmn_err(CE_CONT, " 0 4 8 C\n"); 79 cmn_err(CE_CONT, "----------------------------------------\n"); 80 81 for (cnt = 1; cnt <= count; cnt++) { 82 (void) sprintf(sp, "%10x", *b32++); 83 sp += 10; 84 if (cnt % 4 == 0) { 85 cmn_err(CE_CONT, "%s\n", str); 86 sp = &str[0]; 87 } 88 } 89 break; 90 case 16: 91 cmn_err(CE_CONT, " 0 2 4 6 8 A C" 92 " E\n"); 93 cmn_err(CE_CONT, "------------------------------------------" 94 "------\n"); 95 96 for (cnt = 1; cnt <= count; cnt++) { 97 (void) sprintf(sp, "%6x", *b16++); 98 sp += 6; 99 if (cnt % 8 == 0) { 100 cmn_err(CE_CONT, "%s\n", str); 101 sp = &str[0]; 102 } 103 } 104 break; 105 case 8: 106 cmn_err(CE_CONT, " 0 1 2 3 4 5 6 7 8 9 " 107 "A B C D E F\n"); 108 cmn_err(CE_CONT, "---------------------------------" 109 "-------------------------------\n"); 110 111 for (cnt = 1; cnt <= count; cnt++) { 112 (void) sprintf(sp, "%4x", *b8++); 113 sp += 4; 114 if (cnt % 16 == 0) { 115 cmn_err(CE_CONT, "%s\n", str); 116 sp = &str[0]; 117 } 118 } 119 break; 120 default: 121 break; 122 } 123 if (sp != &str[0]) { 124 cmn_err(CE_CONT, "%s\n", str); 125 } 126 } 127 128 /* 129 * ql_el_msg 130 * Extended logging message 131 * 132 * Input: 133 * ha: adapter state pointer. 134 * fn: function name. 135 * ce: level 136 * ...: Variable argument list. 137 * 138 * Context: 139 * Kernel/Interrupt context. 140 */ 141 void 142 ql_el_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...) 143 { 144 char *s, *fmt, *fmt1; 145 /* 146 * EL_BUFFER_RESERVE 256 is the max # of bytes 147 * that driver's log could be collected. 148 * add 3 more buytes for safely maniplulation. 149 */ 150 char buf[EL_BUFFER_RESERVE + 3]; 151 char buf1[QL_LOG_LENGTH]; 152 size_t tmp, rval, rval1, left; 153 va_list vl; 154 ql_trace_desc_t *desc; 155 ql_trace_entry_t *entry; 156 uint32_t cindex, count; 157 timespec_t time; 158 159 if (ha == NULL && (ha = ql_hba.first->base_address) == NULL) { 160 return; 161 } 162 163 desc = ha->ql_trace_desc; 164 165 (void) bzero((void *)&buf[0], EL_BUFFER_RESERVE + 3); 166 fmt1 = &buf[0]; 167 168 TRACE_BUFFER_LOCK(ha); 169 170 /* locate the entry to be filled out */ 171 cindex = desc->nindex; 172 entry = &desc->trace_buffer[cindex]; 173 174 count = desc->count; 175 176 desc->end = desc->nindex; 177 desc->nindex++; 178 179 if (desc->nindex == desc->nentries) { 180 desc->nindex = 0; 181 } 182 183 if (desc->csize < desc->nentries) { 184 desc->csize++; 185 } else { 186 /* 187 * once wrapped, csize is fixed. 188 * so we have to adjust start point 189 */ 190 desc->start = desc->nindex; 191 } 192 193 gethrestime(&time); 194 195 rval = snprintf(fmt1, (size_t)EL_BUFFER_RESERVE, 196 QL_BANG "%d=>QEL %s(%d,%d,%d):: %s, ", count, QL_NAME, 197 ha->instance, ha->vp_index, ha->pci_function_number, fn); 198 199 rval1 = rval; 200 201 va_start(vl, ce); 202 s = va_arg(vl, char *); 203 204 fmt = fmt1 + rval; 205 206 tmp = vsnprintf(fmt, 207 (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl); 208 209 va_end(vl); 210 211 rval += tmp; 212 213 if (rval > QL_LOG_LENGTH - 1) { 214 left = rval - (QL_LOG_LENGTH - 1); 215 216 /* store the remaining string */ 217 (void) strncpy(buf1, fmt1 + (QL_LOG_LENGTH - 1), left); 218 219 (void) strncpy(entry->buf, fmt1, (QL_LOG_LENGTH - 1)); 220 entry->buf[QL_LOG_LENGTH - 1] = '\n'; 221 222 bcopy((void *)&time, (void *)&entry->hs_time, 223 sizeof (timespec_t)); 224 225 /* 226 * remaining msg will be stored in the nex entry 227 * with same timestamp and same sequence number 228 */ 229 cindex = desc->nindex; 230 entry = &desc->trace_buffer[cindex]; 231 232 desc->end = desc->nindex; 233 desc->nindex++; 234 235 if (desc->nindex == desc->nentries) { 236 desc->nindex = 0; 237 } 238 239 if (desc->csize < desc->nentries) { 240 desc->csize++; 241 } else { 242 desc->start = desc->nindex; 243 } 244 245 (void) strncpy(&entry->buf[0], fmt1, rval1); 246 (void) strncpy(&entry->buf[rval1], &buf1[0], left); 247 entry->buf[rval1 + left] = 0; 248 249 bcopy((void *)&time, (void *)&entry->hs_time, 250 sizeof (timespec_t)); 251 252 if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) { 253 cmn_err(ce, fmt1); 254 } 255 256 desc->count++; 257 258 TRACE_BUFFER_UNLOCK(ha); 259 return; 260 } 261 262 desc->count++; 263 bcopy((void *)&time, (void *)&entry->hs_time, 264 sizeof (timespec_t)); 265 266 (void) strncpy(entry->buf, fmt1, sizeof (entry->buf)); 267 entry->buf[rval] = 0; 268 269 TRACE_BUFFER_UNLOCK(ha); 270 271 if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) { 272 cmn_err(ce, fmt1); 273 } 274 } 275 276 /* 277 * ql_dbg_msg 278 * Extended logging message 279 * 280 * Input: 281 * ha: adapter state pointer. 282 * fn: function name. 283 * ce: level 284 * ...: Variable argument list. 285 * 286 * Context: 287 * Kernel/Interrupt context. 288 */ 289 void 290 ql_dbg_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...) 291 { 292 uint32_t el_msg_num; 293 char *s; 294 char fmt[EL_BUFFER_RESERVE]; 295 va_list vl; 296 297 va_start(vl, ce); 298 299 s = va_arg(vl, char *); 300 301 if (ql_enable_ellock) { 302 /* 303 * Used when messages are *maybe* being lost. Adds 304 * a unique number to the message to one can see if 305 * any messages have been dropped. NB: This slows 306 * down the driver, which may make the issue disappear. 307 */ 308 GLOBAL_EL_LOCK(); 309 el_msg_num = ++el_message_number; 310 GLOBAL_EL_UNLOCK(); 311 if (ha == NULL) { 312 (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s, " 313 "%s", el_msg_num, fn, s); 314 } else { 315 (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s" 316 "(%d,%d,%d): %s", el_msg_num, fn, ha->instance, 317 ha->vp_index, ha->pci_function_number, s); 318 } 319 } else { 320 if (ha == NULL) { 321 (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s, " 322 "%s", fn, s); 323 } else { 324 (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s" 325 "(%d,%d,%d): %s", fn, ha->instance, ha->vp_index, 326 ha->pci_function_number, s); 327 } 328 } 329 330 vcmn_err(ce, fmt, vl); 331 332 va_end(vl); 333 } 334 335 /* 336 * ql_stacktrace 337 * Prints out current stack 338 * 339 * Input: 340 * ha: adapter state pointer. 341 * 342 * Context: 343 * Kernel/Interrupt context. 344 */ 345 void 346 ql_stacktrace(ql_adapter_state_t *ha) 347 { 348 int depth, i; 349 pc_t pcstack[DEBUG_STK_DEPTH]; 350 char *sym = NULL; 351 ulong_t off; 352 353 depth = getpcstack(&pcstack[0], DEBUG_STK_DEPTH); 354 355 cmn_err(CE_CONT, "%s(%d,%d): ---------- \n", QL_NAME, ha->instance, 356 ha->vp_index); 357 for (i = 0; i < MIN(depth, DEBUG_STK_DEPTH); i++) { 358 sym = kobj_getsymname((uintptr_t)pcstack[i], &off); 359 360 if (sym == NULL) { 361 cmn_err(CE_CONT, "%s(%d,%d): sym is NULL\n", QL_NAME, 362 ha->instance, ha->vp_index); 363 } else { 364 cmn_err(CE_CONT, "%s(%d,%d): %s+%lx\n", QL_NAME, 365 ha->instance, ha->vp_index, sym ? sym : "?", off); 366 } 367 } 368 cmn_err(CE_CONT, "%s(%d,%d): ---------- \n", QL_NAME, ha->instance, 369 ha->vp_index); 370 } 371 372 /* 373 * ql_flash_errlog 374 * Adds error to flash error log. 375 * Entry Layout: 376 * uint32_t TimeStamp; 377 * uint16_t CodeData[4]; 378 * 379 * Input: 380 * ha: adapter state pointer. 381 * code: Error code 382 * d1-d3: Error code data 383 * 384 * Returns: 385 * ql local function return status code. 386 * 387 * Context: 388 * Kernel/Interrupt context. 389 */ 390 int 391 ql_flash_errlog(ql_adapter_state_t *ha, uint16_t code, uint16_t d1, 392 uint16_t d2, uint16_t d3) 393 { 394 char *s; 395 uint32_t marker[2], fdata[2], faddr; 396 int rval; 397 398 QL_PRINT_3(ha, "started\n"); 399 400 if (ha->flash_errlog_start == 0) { 401 return (QL_NOT_SUPPORTED); 402 } 403 404 EL(ha, "code=%xh, d1=%xh, d2=%xh, d3=%xh\n", code, d1, d2, d3); 405 406 /* 407 * If marker not already found, locate or write marker. 408 */ 409 if (!(ha->flags & FLASH_ERRLOG_MARKER)) { 410 411 /* Create marker. */ 412 marker[0] = CHAR_TO_LONG(ha->fw_subminor_version, 413 ha->fw_minor_version, ha->fw_major_version, 'S'); 414 415 /* 416 * Version should be of the format: YYYYMMDD-v.vv 417 */ 418 if ((strlen(QL_VERSION) > 9) && (QL_VERSION[8] == '-')) { 419 s = &QL_VERSION[9]; 420 } else { 421 s = QL_VERSION; 422 } 423 424 for (marker[1] = 0; *s != '\0'; s++) { 425 if (*s >= '0' && *s <= '9') { 426 marker[1] <<= 4; 427 marker[1] |= *s - '0'; 428 } else if (*s != '.') { 429 break; 430 } 431 } 432 433 /* Locate marker. */ 434 ha->flash_errlog_ptr = ha->flash_errlog_start; 435 for (;;) { 436 faddr = ha->flash_data_addr | ha->flash_errlog_ptr; 437 (void) ql_24xx_read_flash(ha, faddr++, &fdata[0]); 438 (void) ql_24xx_read_flash(ha, faddr++, &fdata[1]); 439 if (fdata[0] == 0xffffffff && fdata[1] == 0xffffffff) { 440 break; 441 } 442 (void) ql_24xx_read_flash(ha, faddr++, &fdata[0]); 443 (void) ql_24xx_read_flash(ha, faddr++, &fdata[1]); 444 ha->flash_errlog_ptr += FLASH_ERRLOG_ENTRY_SIZE; 445 if (ha->flash_errlog_ptr >= 446 ha->flash_errlog_start + FLASH_ERRLOG_SIZE) { 447 EL(ha, "log full\n"); 448 return (QL_MEMORY_FULL); 449 } 450 if (fdata[0] == marker[0] && fdata[1] == marker[1]) { 451 ha->flags |= FLASH_ERRLOG_MARKER; 452 break; 453 } 454 } 455 456 /* No marker, write it. */ 457 if (!(ha->flags & FLASH_ERRLOG_MARKER)) { 458 ha->flags |= FLASH_ERRLOG_MARKER; 459 rval = ql_flash_errlog_store(ha, marker); 460 if (rval != QL_SUCCESS) { 461 EL(ha, "failed marker write=%xh\n", rval); 462 return (rval); 463 } 464 } 465 } 466 467 /* 468 * Store error. 469 */ 470 fdata[0] = SHORT_TO_LONG(d1, code); 471 fdata[1] = SHORT_TO_LONG(d3, d2); 472 rval = ql_flash_errlog_store(ha, fdata); 473 if (rval != QL_SUCCESS) { 474 EL(ha, "failed error write=%xh\n", rval); 475 } else { 476 /*EMPTY*/ 477 QL_PRINT_3(ha, "done\n"); 478 } 479 480 return (rval); 481 } 482 483 /* 484 * ql_flash_errlog_store 485 * Stores error to flash. 486 * Entry Layout: 487 * uint32_t TimeStamp; 488 * uint16_t CodeData[4]; 489 * 490 * Input: 491 * ha: adapter state pointer. 492 * fdata: Error code plus data. 493 * ha->flash_errlog_ptr: Current Flash error pointer. 494 * 495 * Output: 496 * ha->flash_errlog_ptr: updated pointer. 497 * 498 * Returns: 499 * ql local function return status code. 500 * 501 * Context: 502 * Kernel/Interrupt context. 503 */ 504 static int 505 ql_flash_errlog_store(ql_adapter_state_t *ha, uint32_t *fdata) 506 { 507 int rval; 508 uint64_t time; 509 uint32_t d1, d2, faddr; 510 511 QL_PRINT_3(ha, "started\n"); 512 513 /* Locate first empty entry */ 514 for (;;) { 515 if (ha->flash_errlog_ptr >= 516 ha->flash_errlog_start + FLASH_ERRLOG_SIZE) { 517 EL(ha, "log full\n"); 518 return (QL_MEMORY_FULL); 519 } 520 521 faddr = ha->flash_data_addr | ha->flash_errlog_ptr; 522 ha->flash_errlog_ptr += FLASH_ERRLOG_ENTRY_SIZE; 523 (void) ql_24xx_read_flash(ha, faddr, &d1); 524 (void) ql_24xx_read_flash(ha, faddr + 1, &d2); 525 if (d1 == 0xffffffff && d2 == 0xffffffff) { 526 (void) drv_getparm(TIME, &time); 527 528 /* Enable flash write. */ 529 if ((rval = ql_24xx_unprotect_flash(ha)) != 530 QL_SUCCESS) { 531 EL(ha, "unprotect_flash failed, rval=%xh\n", 532 rval); 533 return (rval); 534 } 535 536 (void) ql_24xx_write_flash(ha, faddr++, LSD(time)); 537 (void) ql_24xx_write_flash(ha, faddr++, MSD(time)); 538 (void) ql_24xx_write_flash(ha, faddr++, *fdata++); 539 (void) ql_24xx_write_flash(ha, faddr++, *fdata); 540 541 /* Enable flash write-protection. */ 542 ql_24xx_protect_flash(ha); 543 break; 544 } 545 } 546 547 QL_PRINT_3(ha, "done\n"); 548 549 return (QL_SUCCESS); 550 } 551