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