182 lines
3.9 KiB
C
182 lines
3.9 KiB
C
|
/*
|
||
|
* Copyright 2014 Cisco Systems, Inc. All rights reserved.
|
||
|
*
|
||
|
* This program is free software; you may redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation; version 2 of the License.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||
|
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*/
|
||
|
|
||
|
#include <linux/module.h>
|
||
|
#include <linux/mempool.h>
|
||
|
#include <linux/errno.h>
|
||
|
#include <linux/vmalloc.h>
|
||
|
|
||
|
#include "snic_io.h"
|
||
|
#include "snic.h"
|
||
|
|
||
|
/*
|
||
|
* snic_get_trc_buf : Allocates a trace record and returns.
|
||
|
*/
|
||
|
struct snic_trc_data *
|
||
|
snic_get_trc_buf(void)
|
||
|
{
|
||
|
struct snic_trc *trc = &snic_glob->trc;
|
||
|
struct snic_trc_data *td = NULL;
|
||
|
unsigned long flags;
|
||
|
|
||
|
spin_lock_irqsave(&trc->lock, flags);
|
||
|
td = &trc->buf[trc->wr_idx];
|
||
|
trc->wr_idx++;
|
||
|
|
||
|
if (trc->wr_idx == trc->max_idx)
|
||
|
trc->wr_idx = 0;
|
||
|
|
||
|
if (trc->wr_idx != trc->rd_idx) {
|
||
|
spin_unlock_irqrestore(&trc->lock, flags);
|
||
|
|
||
|
goto end;
|
||
|
}
|
||
|
|
||
|
trc->rd_idx++;
|
||
|
if (trc->rd_idx == trc->max_idx)
|
||
|
trc->rd_idx = 0;
|
||
|
|
||
|
td->ts = 0; /* Marker for checking the record, for complete data*/
|
||
|
spin_unlock_irqrestore(&trc->lock, flags);
|
||
|
|
||
|
end:
|
||
|
|
||
|
return td;
|
||
|
} /* end of snic_get_trc_buf */
|
||
|
|
||
|
/*
|
||
|
* snic_fmt_trc_data : Formats trace data for printing.
|
||
|
*/
|
||
|
static int
|
||
|
snic_fmt_trc_data(struct snic_trc_data *td, char *buf, int buf_sz)
|
||
|
{
|
||
|
int len = 0;
|
||
|
struct timespec64 tmspec;
|
||
|
|
||
|
jiffies_to_timespec64(td->ts, &tmspec);
|
||
|
|
||
|
len += snprintf(buf, buf_sz,
|
||
|
"%llu.%09lu %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n",
|
||
|
tmspec.tv_sec,
|
||
|
tmspec.tv_nsec,
|
||
|
td->fn,
|
||
|
td->hno,
|
||
|
td->tag,
|
||
|
td->data[0], td->data[1], td->data[2], td->data[3],
|
||
|
td->data[4]);
|
||
|
|
||
|
return len;
|
||
|
} /* end of snic_fmt_trc_data */
|
||
|
|
||
|
/*
|
||
|
* snic_get_trc_data : Returns a formatted trace buffer.
|
||
|
*/
|
||
|
int
|
||
|
snic_get_trc_data(char *buf, int buf_sz)
|
||
|
{
|
||
|
struct snic_trc_data *td = NULL;
|
||
|
struct snic_trc *trc = &snic_glob->trc;
|
||
|
unsigned long flags;
|
||
|
|
||
|
spin_lock_irqsave(&trc->lock, flags);
|
||
|
if (trc->rd_idx == trc->wr_idx) {
|
||
|
spin_unlock_irqrestore(&trc->lock, flags);
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
td = &trc->buf[trc->rd_idx];
|
||
|
|
||
|
if (td->ts == 0) {
|
||
|
/* write in progress. */
|
||
|
spin_unlock_irqrestore(&trc->lock, flags);
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
trc->rd_idx++;
|
||
|
if (trc->rd_idx == trc->max_idx)
|
||
|
trc->rd_idx = 0;
|
||
|
spin_unlock_irqrestore(&trc->lock, flags);
|
||
|
|
||
|
return snic_fmt_trc_data(td, buf, buf_sz);
|
||
|
} /* end of snic_get_trc_data */
|
||
|
|
||
|
/*
|
||
|
* snic_trc_init() : Configures Trace Functionality for snic.
|
||
|
*/
|
||
|
int
|
||
|
snic_trc_init(void)
|
||
|
{
|
||
|
struct snic_trc *trc = &snic_glob->trc;
|
||
|
void *tbuf = NULL;
|
||
|
int tbuf_sz = 0, ret;
|
||
|
|
||
|
tbuf_sz = (snic_trace_max_pages * PAGE_SIZE);
|
||
|
tbuf = vmalloc(tbuf_sz);
|
||
|
if (!tbuf) {
|
||
|
SNIC_ERR("Failed to Allocate Trace Buffer Size. %d\n", tbuf_sz);
|
||
|
SNIC_ERR("Trace Facility not enabled.\n");
|
||
|
ret = -ENOMEM;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
memset(tbuf, 0, tbuf_sz);
|
||
|
trc->buf = (struct snic_trc_data *) tbuf;
|
||
|
spin_lock_init(&trc->lock);
|
||
|
|
||
|
ret = snic_trc_debugfs_init();
|
||
|
if (ret) {
|
||
|
SNIC_ERR("Failed to create Debugfs Files.\n");
|
||
|
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
trc->max_idx = (tbuf_sz / SNIC_TRC_ENTRY_SZ);
|
||
|
trc->rd_idx = trc->wr_idx = 0;
|
||
|
trc->enable = true;
|
||
|
SNIC_INFO("Trace Facility Enabled.\n Trace Buffer SZ %lu Pages.\n",
|
||
|
tbuf_sz / PAGE_SIZE);
|
||
|
ret = 0;
|
||
|
|
||
|
return ret;
|
||
|
|
||
|
error:
|
||
|
snic_trc_free();
|
||
|
|
||
|
return ret;
|
||
|
} /* end of snic_trc_init */
|
||
|
|
||
|
/*
|
||
|
* snic_trc_free : Releases the trace buffer and disables the tracing.
|
||
|
*/
|
||
|
void
|
||
|
snic_trc_free(void)
|
||
|
{
|
||
|
struct snic_trc *trc = &snic_glob->trc;
|
||
|
|
||
|
trc->enable = false;
|
||
|
snic_trc_debugfs_term();
|
||
|
|
||
|
if (trc->buf) {
|
||
|
vfree(trc->buf);
|
||
|
trc->buf = NULL;
|
||
|
}
|
||
|
|
||
|
SNIC_INFO("Trace Facility Disabled.\n");
|
||
|
} /* end of snic_trc_free */
|