Print this page
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>

@@ -17,26 +17,25 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 
-/* Copyright 2009 QLogic Corporation */
+/* Copyright 2015 QLogic Corporation */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident   "Copyright 2009 QLogic Corporation; ql_debug.c"
+#pragma ident   "Copyright 2015 QLogic Corporation; ql_debug.c"
 
 /*
  * Qlogic ISP22xx/ISP23xx/ISP24xx FCA driver source
  *
  * ***********************************************************************
  * *                                                                    **
  * *                            NOTICE                                  **
- * *            COPYRIGHT (C) 1996-2009 QLOGIC CORPORATION              **
+ * *            COPYRIGHT (C) 1996-2015 QLOGIC CORPORATION              **
  * *                    ALL RIGHTS RESERVED                             **
  * *                                                                    **
  * ***********************************************************************
  *
  */

@@ -44,12 +43,10 @@
 #include <ql_apps.h>
 #include <ql_api.h>
 #include <ql_debug.h>
 
 static int ql_flash_errlog_store(ql_adapter_state_t *, uint32_t *);
-int ql_validate_trace_desc(ql_adapter_state_t *ha);
-char *ql_find_trace_start(ql_adapter_state_t *ha);
 
 /*
  * Global Data.
  */
 uint32_t        el_message_number = 0;

@@ -144,94 +141,144 @@
  *      Kernel/Interrupt context.
  */
 void
 ql_el_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...)
 {
-        uint32_t        el_msg_num;
-        char            *s, *fmt = 0, *fmt1 = 0;
-        char            fmt2[256];
-        int             rval, tmp;
-        int             tracing = 0;
+        char            *s, *fmt, *fmt1;
+        /*
+         * EL_BUFFER_RESERVE 256 is the max # of bytes
+         * that driver's log could be collected.
+         * add 3 more buytes for safely maniplulation.
+         */
+        char                    buf[EL_BUFFER_RESERVE + 3];
+        char                    buf1[QL_LOG_LENGTH];
+        size_t                  tmp, rval, rval1, left;
         va_list         vl;
+        ql_trace_desc_t         *desc;
+        ql_trace_entry_t        *entry;
+        uint32_t                cindex, count;
+        timespec_t              time;
 
-        /* Tracing is the default but it can be disabled. */
-        if ((CFG_IST(ha, CFG_DISABLE_EXTENDED_LOGGING_TRACE) == 0) &&
-            (rval = ql_validate_trace_desc(ha) == DDI_SUCCESS)) {
-                tracing = 1;
+        if (ha == NULL && (ha = ql_hba.first->base_address) == NULL) {
+                return;
+        }
 
+        desc = ha->ql_trace_desc;
+
+        (void) bzero((void *)&buf[0], EL_BUFFER_RESERVE + 3);
+        fmt1 = &buf[0];
+
                 TRACE_BUFFER_LOCK(ha);
 
+        /* locate the entry to be filled out */
+        cindex = desc->nindex;
+        entry = &desc->trace_buffer[cindex];
+
+        count = desc->count;
+
+        desc->end = desc->nindex;
+        desc->nindex++;
+
+        if (desc->nindex == desc->nentries) {
+                desc->nindex = 0;
+        }
+
+        if (desc->csize < desc->nentries) {
+                desc->csize++;
+        } else {
                 /*
-                 * Ensure enough space for the string. Wrap to
-                 * start when default message allocation size
-                 * would overrun the end.
+                 * once wrapped, csize is fixed.
+                 * so we have to adjust start point
                  */
-                if ((ha->el_trace_desc->next + EL_BUFFER_RESERVE) >=
-                    ha->el_trace_desc->trace_buffer_size) {
-                        fmt = ha->el_trace_desc->trace_buffer;
-                        ha->el_trace_desc->next = 0;
-                } else {
-                        fmt = ha->el_trace_desc->trace_buffer +
-                            ha->el_trace_desc->next;
+                desc->start = desc->nindex;
                 }
-        }
-        /* if no buffer use the stack */
-        if (fmt == NULL) {
-                fmt = fmt2;
-        }
 
-        va_start(vl, ce);
+        gethrestime(&time);
 
+        rval = snprintf(fmt1, (size_t)EL_BUFFER_RESERVE,
+            QL_BANG "%d=>QEL %s(%d,%d,%d):: %s, ", count, QL_NAME,
+            ha->instance, ha->vp_index, ha->pci_function_number, fn);
+
+        rval1 = rval;
+
+        va_start(vl, ce);
         s = va_arg(vl, char *);
 
-        if (ql_enable_ellock) {
-                /*
-                 * Used when messages are *maybe* being lost.  Adds
-                 * a unique number to the message so one can see if
-                 * any messages have been dropped. NB: This slows
-                 * down the driver, which may make the issue disappear.
-                 */
-                GLOBAL_EL_LOCK();
-                el_msg_num = ++el_message_number;
-                GLOBAL_EL_UNLOCK();
+        fmt = fmt1 + rval;
 
-                rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
-                    QL_BANG "QEL%d %s(%d,%d): %s, ", el_msg_num, QL_NAME,
-                    ha->instance, ha->vp_index, fn);
-                fmt1 = fmt + rval;
-                tmp = (int)vsnprintf(fmt1,
+        tmp = vsnprintf(fmt,
                     (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
+
+        va_end(vl);
+
                 rval += tmp;
-        } else {
-                rval = (int)snprintf(fmt, (size_t)EL_BUFFER_RESERVE,
-                    QL_BANG "QEL %s(%d,%d): %s, ", QL_NAME, ha->instance,
-                    ha->vp_index, fn);
-                fmt1 = fmt + rval;
-                tmp = (int)vsnprintf(fmt1,
-                    (size_t)(uint32_t)((int)EL_BUFFER_RESERVE - rval), s, vl);
-                rval += tmp;
-        }
 
+        if (rval > QL_LOG_LENGTH - 1) {
+                left = rval - (QL_LOG_LENGTH - 1);
+
+                /* store the remaining string */
+                (void) strncpy(buf1, fmt1 + (QL_LOG_LENGTH - 1), left);
+
+                (void) strncpy(entry->buf, fmt1, (QL_LOG_LENGTH - 1));
+                entry->buf[QL_LOG_LENGTH - 1] = '\n';
+
+                bcopy((void *)&time, (void *)&entry->hs_time,
+                    sizeof (timespec_t));
+
         /*
-         * Calculate the offset where the next message will go,
-         * skipping the NULL.
+                 * remaining msg will be stored in the nex entry
+                 * with same timestamp and same sequence number
          */
-        if (tracing) {
-                uint16_t next = (uint16_t)(rval += 1);
-                ha->el_trace_desc->next += next;
-                TRACE_BUFFER_UNLOCK(ha);
+                cindex = desc->nindex;
+                entry = &desc->trace_buffer[cindex];
+
+                desc->end = desc->nindex;
+                desc->nindex++;
+
+                if (desc->nindex == desc->nentries) {
+                        desc->nindex = 0;
         }
 
+                if (desc->csize < desc->nentries) {
+                        desc->csize++;
+                } else {
+                        desc->start = desc->nindex;
+                }
+
+                (void) strncpy(&entry->buf[0], fmt1, rval1);
+                (void) strncpy(&entry->buf[rval1], &buf1[0], left);
+                entry->buf[rval1 + left] = 0;
+
+                bcopy((void *)&time, (void *)&entry->hs_time,
+                    sizeof (timespec_t));
+
         if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) {
-                cmn_err(ce, fmt);
+                        cmn_err(ce, fmt1);
         }
 
-        va_end(vl);
+                desc->count++;
+
+                TRACE_BUFFER_UNLOCK(ha);
+                return;
+        }
+
+        desc->count++;
+        bcopy((void *)&time, (void *)&entry->hs_time,
+            sizeof (timespec_t));
+
+        (void) strncpy(entry->buf, fmt1, sizeof (entry->buf));
+        entry->buf[rval] = 0;
+
+        TRACE_BUFFER_UNLOCK(ha);
+
+        if (CFG_IST(ha, CFG_ENABLE_EXTENDED_LOGGING)) {
+                cmn_err(ce, fmt1);
+        }
 }
 
 /*
- * ql_el_msg
+ * ql_dbg_msg
  *      Extended logging message
  *
  * Input:
  *      ha:     adapter state pointer.
  *      fn:     function name.

@@ -240,15 +287,15 @@
  *
  * Context:
  *      Kernel/Interrupt context.
  */
 void
-ql_dbg_msg(const char *fn, int ce, ...)
+ql_dbg_msg(ql_adapter_state_t *ha, const char *fn, int ce, ...)
 {
         uint32_t        el_msg_num;
         char            *s;
-        char            fmt[256];
+        char            fmt[EL_BUFFER_RESERVE];
         va_list         vl;
 
         va_start(vl, ce);
 
         s = va_arg(vl, char *);

@@ -261,16 +308,28 @@
                  * down the driver, which may make the issue disappear.
                  */
                 GLOBAL_EL_LOCK();
                 el_msg_num = ++el_message_number;
                 GLOBAL_EL_UNLOCK();
-                (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s %s, %s",
-                    el_msg_num, QL_NAME, fn, s);
+                if (ha == NULL) {
+                        (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s, "
+                            "%s", el_msg_num, fn, s);
         } else {
-                (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s %s, %s",
-                    QL_NAME, fn, s);
+                        (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP%d: %s"
+                            "(%d,%d,%d): %s", el_msg_num, fn, ha->instance,
+                            ha->vp_index, ha->pci_function_number, s);
         }
+        } else {
+                if (ha == NULL) {
+                        (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s, "
+                            "%s", fn, s);
+                } else {
+                        (void) snprintf(fmt, EL_BUFFER_RESERVE, "QLP: %s"
+                            "(%d,%d,%d): %s", fn, ha->instance, ha->vp_index,
+                            ha->pci_function_number, s);
+                }
+        }
 
         vcmn_err(ce, fmt, vl);
 
         va_end(vl);
 }

@@ -336,11 +395,11 @@
 {
         char            *s;
         uint32_t        marker[2], fdata[2], faddr;
         int             rval;
 
-        QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
+        QL_PRINT_3(ha, "started\n");
 
         if (ha->flash_errlog_start == 0) {
                 return (QL_NOT_SUPPORTED);
         }
 

@@ -415,11 +474,11 @@
         rval = ql_flash_errlog_store(ha, fdata);
         if (rval != QL_SUCCESS) {
                 EL(ha, "failed error write=%xh\n", rval);
         } else {
                 /*EMPTY*/
-                QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
+                QL_PRINT_3(ha, "done\n");
         }
 
         return (rval);
 }
 

@@ -449,11 +508,11 @@
 {
         int             rval;
         uint64_t        time;
         uint32_t        d1, d2, faddr;
 
-        QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance);
+        QL_PRINT_3(ha, "started\n");
 
         /* Locate first empty entry */
         for (;;) {
                 if (ha->flash_errlog_ptr >=
                     ha->flash_errlog_start + FLASH_ERRLOG_SIZE) {

@@ -485,131 +544,9 @@
                         ql_24xx_protect_flash(ha);
                         break;
                 }
         }
 
-        QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance);
+        QL_PRINT_3(ha, "done\n");
 
         return (QL_SUCCESS);
-}
-
-/*
- * ql_dump_el_trace_buffer
- *       Outputs extended logging trace buffer.
- *
- * Input:
- *      ha:     adapter state pointer.
- */
-void
-ql_dump_el_trace_buffer(ql_adapter_state_t *ha)
-{
-        char            *dump_start = NULL;
-        char            *dump_current = NULL;
-        char            *trace_start;
-        char            *trace_end;
-        int             wrapped = 0;
-        int             rval;
-
-        TRACE_BUFFER_LOCK(ha);
-
-        rval = ql_validate_trace_desc(ha);
-        if (rval != NULL) {
-                cmn_err(CE_CONT, "%s(%d) Dump EL trace - invalid desc\n",
-                    QL_NAME, ha->instance);
-        } else if ((dump_start = ql_find_trace_start(ha)) != NULL) {
-                dump_current = dump_start;
-                trace_start = ha->el_trace_desc->trace_buffer;
-                trace_end = trace_start +
-                    ha->el_trace_desc->trace_buffer_size;
-
-                cmn_err(CE_CONT, "%s(%d) Dump EL trace - start %p %p\n",
-                    QL_NAME, ha->instance,
-                    (void *)dump_start, (void *)trace_start);
-
-                while (((uintptr_t)dump_current - (uintptr_t)trace_start) <=
-                    (uintptr_t)ha->el_trace_desc->trace_buffer_size) {
-                        /* Show it... */
-                        cmn_err(CE_CONT, "%p - %s", (void *)dump_current,
-                            dump_current);
-                        /* Make the next the current */
-                        dump_current += (strlen(dump_current) + 1);
-                        /* check for wrap */
-                        if ((dump_current + EL_BUFFER_RESERVE) >= trace_end) {
-                                dump_current = trace_start;
-                                wrapped = 1;
-                        } else if (wrapped) {
-                                /* Don't go past next. */
-                                if ((trace_start + ha->el_trace_desc->next) <=
-                                    dump_current) {
-                                        break;
-                                }
-                        } else if (*dump_current == NULL) {
-                                break;
-                        }
-                }
-        }
-        TRACE_BUFFER_UNLOCK(ha);
-}
-
-/*
- * ql_validate_trace_desc
- *       Ensures the extended logging trace descriptor is good
- *
- * Input:
- *      ha:     adapter state pointer.
- *
- * Returns:
- *      ql local function return status code.
- */
-int
-ql_validate_trace_desc(ql_adapter_state_t *ha)
-{
-        int     rval = DDI_SUCCESS;
-
-        if (ha->el_trace_desc == NULL) {
-                rval = DDI_FAILURE;
-        } else if (ha->el_trace_desc->trace_buffer == NULL) {
-                rval = DDI_FAILURE;
-        }
-        return (rval);
-}
-
-/*
- * ql_find_trace_start
- *       Locate the oldest extended logging trace entry.
- *
- * Input:
- *      ha:     adapter state pointer.
- *
- * Returns:
- *      Pointer to a string.
- *
- * Context:
- *      Kernel/Interrupt context.
- */
-char *
-ql_find_trace_start(ql_adapter_state_t *ha)
-{
-        char    *trace_start = 0;
-        char    *trace_next  = 0;
-
-        trace_next = ha->el_trace_desc->trace_buffer + ha->el_trace_desc->next;
-
-        /*
-         * if the buffer has not wrapped next will point at a null so
-         * start is the beginning of the buffer.  if next points at a char
-         * then we must traverse the buffer until a null is detected and
-         * that will be the beginning of the oldest whole object in the buffer
-         * which is the start.
-         */
-
-        if ((trace_next + EL_BUFFER_RESERVE) >=
-            (ha->el_trace_desc->trace_buffer +
-            ha->el_trace_desc->trace_buffer_size)) {
-                trace_start = ha->el_trace_desc->trace_buffer;
-        } else if (*trace_next != NULL) {
-                trace_start = trace_next + (strlen(trace_next) + 1);
-        } else {
-                trace_start = ha->el_trace_desc->trace_buffer;
-        }
-        return (trace_start);
 }