1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright 2014 Cisco Systems, Inc. All rights reserved.
3
4#include <linux/module.h>
5#include <linux/mempool.h>
6#include <linux/errno.h>
7#include <linux/vmalloc.h>
8
9#include "snic_io.h"
10#include "snic.h"
11
12/*
13 * snic_get_trc_buf : Allocates a trace record and returns.
14 */
15struct snic_trc_data *
16snic_get_trc_buf(void)
17{
18 struct snic_trc *trc = &snic_glob->trc;
19 struct snic_trc_data *td = NULL;
20 unsigned long flags;
21
22 spin_lock_irqsave(&trc->lock, flags);
23 td = &trc->buf[trc->wr_idx];
24 trc->wr_idx++;
25
26 if (trc->wr_idx == trc->max_idx)
27 trc->wr_idx = 0;
28
29 if (trc->wr_idx != trc->rd_idx) {
30 spin_unlock_irqrestore(lock: &trc->lock, flags);
31
32 goto end;
33 }
34
35 trc->rd_idx++;
36 if (trc->rd_idx == trc->max_idx)
37 trc->rd_idx = 0;
38
39 td->ts = 0; /* Marker for checking the record, for complete data*/
40 spin_unlock_irqrestore(lock: &trc->lock, flags);
41
42end:
43
44 return td;
45} /* end of snic_get_trc_buf */
46
47/*
48 * snic_fmt_trc_data : Formats trace data for printing.
49 */
50static int
51snic_fmt_trc_data(struct snic_trc_data *td, char *buf, int buf_sz)
52{
53 int len = 0;
54 struct timespec64 tmspec;
55
56 jiffies_to_timespec64(jiffies: td->ts, value: &tmspec);
57
58 len += snprintf(buf, size: buf_sz,
59 fmt: "%llu.%09lu %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n",
60 tmspec.tv_sec,
61 tmspec.tv_nsec,
62 td->fn,
63 td->hno,
64 td->tag,
65 td->data[0], td->data[1], td->data[2], td->data[3],
66 td->data[4]);
67
68 return len;
69} /* end of snic_fmt_trc_data */
70
71/*
72 * snic_get_trc_data : Returns a formatted trace buffer.
73 */
74int
75snic_get_trc_data(char *buf, int buf_sz)
76{
77 struct snic_trc_data *td = NULL;
78 struct snic_trc *trc = &snic_glob->trc;
79 unsigned long flags;
80
81 spin_lock_irqsave(&trc->lock, flags);
82 if (trc->rd_idx == trc->wr_idx) {
83 spin_unlock_irqrestore(lock: &trc->lock, flags);
84
85 return -1;
86 }
87 td = &trc->buf[trc->rd_idx];
88
89 if (td->ts == 0) {
90 /* write in progress. */
91 spin_unlock_irqrestore(lock: &trc->lock, flags);
92
93 return -1;
94 }
95
96 trc->rd_idx++;
97 if (trc->rd_idx == trc->max_idx)
98 trc->rd_idx = 0;
99 spin_unlock_irqrestore(lock: &trc->lock, flags);
100
101 return snic_fmt_trc_data(td, buf, buf_sz);
102} /* end of snic_get_trc_data */
103
104/*
105 * snic_trc_init() : Configures Trace Functionality for snic.
106 */
107int
108snic_trc_init(void)
109{
110 struct snic_trc *trc = &snic_glob->trc;
111 void *tbuf = NULL;
112 int tbuf_sz = 0, ret;
113
114 tbuf_sz = (snic_trace_max_pages * PAGE_SIZE);
115 tbuf = vzalloc(size: tbuf_sz);
116 if (!tbuf) {
117 SNIC_ERR("Failed to Allocate Trace Buffer Size. %d\n", tbuf_sz);
118 SNIC_ERR("Trace Facility not enabled.\n");
119 ret = -ENOMEM;
120
121 return ret;
122 }
123
124 trc->buf = (struct snic_trc_data *) tbuf;
125 spin_lock_init(&trc->lock);
126
127 snic_trc_debugfs_init();
128
129 trc->max_idx = (tbuf_sz / SNIC_TRC_ENTRY_SZ);
130 trc->rd_idx = trc->wr_idx = 0;
131 trc->enable = true;
132 SNIC_INFO("Trace Facility Enabled.\n Trace Buffer SZ %lu Pages.\n",
133 tbuf_sz / PAGE_SIZE);
134 ret = 0;
135
136 return ret;
137} /* end of snic_trc_init */
138
139/*
140 * snic_trc_free : Releases the trace buffer and disables the tracing.
141 */
142void
143snic_trc_free(void)
144{
145 struct snic_trc *trc = &snic_glob->trc;
146
147 trc->enable = false;
148 snic_trc_debugfs_term();
149
150 if (trc->buf) {
151 vfree(addr: trc->buf);
152 trc->buf = NULL;
153 }
154
155 SNIC_INFO("Trace Facility Disabled.\n");
156} /* end of snic_trc_free */
157

source code of linux/drivers/scsi/snic/snic_trc.c