Merge tag 'drm-misc-fixes-2022-08-16' of git://anongit.freedesktop.org/drm/drm-misc...
[linux-block.git] / drivers / scsi / snic / snic_trc.c
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(&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(&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(td->ts, &tmspec);
57
58         len += snprintf(buf, buf_sz,
59                         "%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(&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(&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(&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(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(trc->buf);
152                 trc->buf = NULL;
153         }
154
155         SNIC_INFO("Trace Facility Disabled.\n");
156 } /* end of snic_trc_free */