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