linux/drivers/scsi/snic/snic_trc.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014 Cisco Systems, Inc.  All rights reserved.
   3 *
   4 * This program is free software; you may redistribute it and/or modify
   5 * it under the terms of the GNU General Public License as published by
   6 * the Free Software Foundation; version 2 of the License.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  15 * SOFTWARE.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/mempool.h>
  20#include <linux/errno.h>
  21#include <linux/vmalloc.h>
  22
  23#include "snic_io.h"
  24#include "snic.h"
  25
  26/*
  27 * snic_get_trc_buf : Allocates a trace record and returns.
  28 */
  29struct snic_trc_data *
  30snic_get_trc_buf(void)
  31{
  32        struct snic_trc *trc = &snic_glob->trc;
  33        struct snic_trc_data *td = NULL;
  34        unsigned long flags;
  35
  36        spin_lock_irqsave(&trc->lock, flags);
  37        td = &trc->buf[trc->wr_idx];
  38        trc->wr_idx++;
  39
  40        if (trc->wr_idx == trc->max_idx)
  41                trc->wr_idx = 0;
  42
  43        if (trc->wr_idx != trc->rd_idx) {
  44                spin_unlock_irqrestore(&trc->lock, flags);
  45
  46                goto end;
  47        }
  48
  49        trc->rd_idx++;
  50        if (trc->rd_idx == trc->max_idx)
  51                trc->rd_idx = 0;
  52
  53        td->ts = 0;     /* Marker for checking the record, for complete data*/
  54        spin_unlock_irqrestore(&trc->lock, flags);
  55
  56end:
  57
  58        return td;
  59} /* end of snic_get_trc_buf */
  60
  61/*
  62 * snic_fmt_trc_data : Formats trace data for printing.
  63 */
  64static int
  65snic_fmt_trc_data(struct snic_trc_data *td, char *buf, int buf_sz)
  66{
  67        int len = 0;
  68        struct timespec tmspec;
  69
  70        jiffies_to_timespec(td->ts, &tmspec);
  71
  72        len += snprintf(buf, buf_sz,
  73                        "%lu.%10lu %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n",
  74                        tmspec.tv_sec,
  75                        tmspec.tv_nsec,
  76                        td->fn,
  77                        td->hno,
  78                        td->tag,
  79                        td->data[0], td->data[1], td->data[2], td->data[3],
  80                        td->data[4]);
  81
  82        return len;
  83} /* end of snic_fmt_trc_data */
  84
  85/*
  86 * snic_get_trc_data : Returns a formatted trace buffer.
  87 */
  88int
  89snic_get_trc_data(char *buf, int buf_sz)
  90{
  91        struct snic_trc_data *td = NULL;
  92        struct snic_trc *trc = &snic_glob->trc;
  93        unsigned long flags;
  94
  95        spin_lock_irqsave(&trc->lock, flags);
  96        if (trc->rd_idx == trc->wr_idx) {
  97                spin_unlock_irqrestore(&trc->lock, flags);
  98
  99                return -1;
 100        }
 101        td = &trc->buf[trc->rd_idx];
 102
 103        if (td->ts == 0) {
 104                /* write in progress. */
 105                spin_unlock_irqrestore(&trc->lock, flags);
 106
 107                return -1;
 108        }
 109
 110        trc->rd_idx++;
 111        if (trc->rd_idx == trc->max_idx)
 112                trc->rd_idx = 0;
 113        spin_unlock_irqrestore(&trc->lock, flags);
 114
 115        return snic_fmt_trc_data(td, buf, buf_sz);
 116} /* end of snic_get_trc_data */
 117
 118/*
 119 * snic_trc_init() : Configures Trace Functionality for snic.
 120 */
 121int
 122snic_trc_init(void)
 123{
 124        struct snic_trc *trc = &snic_glob->trc;
 125        void *tbuf = NULL;
 126        int tbuf_sz = 0, ret;
 127
 128        tbuf_sz = (snic_trace_max_pages * PAGE_SIZE);
 129        tbuf = vmalloc(tbuf_sz);
 130        if (!tbuf) {
 131                SNIC_ERR("Failed to Allocate Trace Buffer Size. %d\n", tbuf_sz);
 132                SNIC_ERR("Trace Facility not enabled.\n");
 133                ret = -ENOMEM;
 134
 135                return ret;
 136        }
 137
 138        memset(tbuf, 0, tbuf_sz);
 139        trc->buf = (struct snic_trc_data *) tbuf;
 140        spin_lock_init(&trc->lock);
 141
 142        ret = snic_trc_debugfs_init();
 143        if (ret) {
 144                SNIC_ERR("Failed to create Debugfs Files.\n");
 145
 146                goto error;
 147        }
 148
 149        trc->max_idx = (tbuf_sz / SNIC_TRC_ENTRY_SZ);
 150        trc->rd_idx = trc->wr_idx = 0;
 151        trc->enable = true;
 152        SNIC_INFO("Trace Facility Enabled.\n Trace Buffer SZ %lu Pages.\n",
 153                  tbuf_sz / PAGE_SIZE);
 154        ret = 0;
 155
 156        return ret;
 157
 158error:
 159        snic_trc_free();
 160
 161        return ret;
 162} /* end of snic_trc_init */
 163
 164/*
 165 * snic_trc_free : Releases the trace buffer and disables the tracing.
 166 */
 167void
 168snic_trc_free(void)
 169{
 170        struct snic_trc *trc = &snic_glob->trc;
 171
 172        trc->enable = false;
 173        snic_trc_debugfs_term();
 174
 175        if (trc->buf) {
 176                vfree(trc->buf);
 177                trc->buf = NULL;
 178        }
 179
 180        SNIC_INFO("Trace Facility Disabled.\n");
 181} /* end of snic_trc_free */
 182