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 */ 157