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 "%ptSp %-25s %3d %4x %16llx %16llx %16llx %16llx %16llx\n", 60 &tmspec, 61 td->fn, 62 td->hno, 63 td->tag, 64 td->data[0], td->data[1], td->data[2], td->data[3], 65 td->data[4]); 66 67 return len; 68 } /* end of snic_fmt_trc_data */ 69 70 /* 71 * snic_get_trc_data : Returns a formatted trace buffer. 72 */ 73 int 74 snic_get_trc_data(char *buf, int buf_sz) 75 { 76 struct snic_trc_data *td = NULL; 77 struct snic_trc *trc = &snic_glob->trc; 78 unsigned long flags; 79 80 spin_lock_irqsave(&trc->lock, flags); 81 if (trc->rd_idx == trc->wr_idx) { 82 spin_unlock_irqrestore(&trc->lock, flags); 83 84 return -1; 85 } 86 td = &trc->buf[trc->rd_idx]; 87 88 if (td->ts == 0) { 89 /* write in progress. */ 90 spin_unlock_irqrestore(&trc->lock, flags); 91 92 return -1; 93 } 94 95 trc->rd_idx++; 96 if (trc->rd_idx == trc->max_idx) 97 trc->rd_idx = 0; 98 spin_unlock_irqrestore(&trc->lock, flags); 99 100 return snic_fmt_trc_data(td, buf, buf_sz); 101 } /* end of snic_get_trc_data */ 102 103 /* 104 * snic_trc_init() : Configures Trace Functionality for snic. 105 */ 106 int 107 snic_trc_init(void) 108 { 109 struct snic_trc *trc = &snic_glob->trc; 110 void *tbuf = NULL; 111 int tbuf_sz = 0, ret; 112 113 tbuf_sz = (snic_trace_max_pages * PAGE_SIZE); 114 tbuf = vzalloc(tbuf_sz); 115 if (!tbuf) { 116 SNIC_ERR("Failed to Allocate Trace Buffer Size. %d\n", tbuf_sz); 117 SNIC_ERR("Trace Facility not enabled.\n"); 118 ret = -ENOMEM; 119 120 return ret; 121 } 122 123 trc->buf = (struct snic_trc_data *) tbuf; 124 spin_lock_init(&trc->lock); 125 126 snic_trc_debugfs_init(); 127 128 trc->max_idx = (tbuf_sz / SNIC_TRC_ENTRY_SZ); 129 trc->rd_idx = trc->wr_idx = 0; 130 trc->enable = true; 131 SNIC_INFO("Trace Facility Enabled.\n Trace Buffer SZ %lu Pages.\n", 132 tbuf_sz / PAGE_SIZE); 133 ret = 0; 134 135 return ret; 136 } /* end of snic_trc_init */ 137 138 /* 139 * snic_trc_free : Releases the trace buffer and disables the tracing. 140 */ 141 void 142 snic_trc_free(void) 143 { 144 struct snic_trc *trc = &snic_glob->trc; 145 146 trc->enable = false; 147 snic_trc_debugfs_term(); 148 149 if (trc->buf) { 150 vfree(trc->buf); 151 trc->buf = NULL; 152 } 153 154 SNIC_INFO("Trace Facility Disabled.\n"); 155 } /* end of snic_trc_free */ 156