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 | */ |
15 | struct snic_trc_data * |
16 | snic_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 | |
42 | end: |
43 | |
44 | return td; |
45 | } /* end of snic_get_trc_buf */ |
46 | |
47 | /* |
48 | * snic_fmt_trc_data : Formats trace data for printing. |
49 | */ |
50 | static int |
51 | snic_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 | */ |
74 | int |
75 | snic_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 | */ |
107 | int |
108 | snic_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 | */ |
142 | void |
143 | snic_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 | |