1 /* 2 * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* 20 * 21 * Permission to use, copy, modify, and/or distribute this software for any 22 * purpose with or without fee is hereby granted, provided that the above 23 * copyright notice and this permission notice appear in all copies. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 26 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 28 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 31 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 32 */ 33 34 #ifndef REMOVE_PKT_LOG 35 #include "ol_txrx_types.h" 36 #include "ol_htt_tx_api.h" 37 #include "ol_tx_desc.h" 38 #include "qdf_mem.h" 39 #include "htt.h" 40 #include "htt_internal.h" 41 #include "pktlog_ac_i.h" 42 #include "wma_api.h" 43 #include "wlan_logging_sock_svc.h" 44 45 #ifdef PKTLOG_HAS_SPECIFIC_DATA 46 void 47 pktlog_hdr_set_specific_data(struct ath_pktlog_hdr *log_hdr, 48 uint32_t type_specific_data) 49 { 50 log_hdr->type_specific_data = type_specific_data; 51 } 52 53 uint32_t 54 pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr) 55 { 56 return log_hdr->type_specific_data; 57 } 58 59 void 60 pktlog_arg_set_specific_data(struct ath_pktlog_arg *plarg, 61 uint32_t type_specific_data) 62 { 63 plarg->type_specific_data = type_specific_data; 64 } 65 66 uint32_t 67 pktlog_arg_get_specific_data(struct ath_pktlog_arg *plarg) 68 { 69 return plarg->type_specific_data; 70 } 71 #endif /* PKTLOG_HAS_SPECIFIC_DATA */ 72 73 void pktlog_getbuf_intsafe(struct ath_pktlog_arg *plarg) 74 { 75 struct ath_pktlog_buf *log_buf; 76 int32_t buf_size; 77 struct ath_pktlog_hdr *log_hdr; 78 int32_t cur_wr_offset; 79 char *log_ptr; 80 struct ath_pktlog_info *pl_info; 81 uint16_t log_type; 82 size_t log_size; 83 uint32_t flags; 84 #ifdef HELIUMPLUS 85 uint8_t mac_id; 86 #endif 87 88 if (!plarg) { 89 qdf_nofl_info("Invalid parg in %s", __func__); 90 return; 91 } 92 93 pl_info = plarg->pl_info; 94 #ifdef HELIUMPLUS 95 mac_id = plarg->macId; 96 log_type = plarg->log_type; 97 #else 98 log_type = plarg->log_type; 99 #endif 100 log_size = plarg->log_size; 101 log_buf = pl_info->buf; 102 flags = plarg->flags; 103 104 if (!log_buf) { 105 qdf_nofl_info("Invalid log_buf in %s", __func__); 106 return; 107 } 108 109 110 buf_size = pl_info->buf_size; 111 cur_wr_offset = log_buf->wr_offset; 112 /* Move read offset to the next entry if there is a buffer overlap */ 113 if (log_buf->rd_offset >= 0) { 114 if ((cur_wr_offset <= log_buf->rd_offset) 115 && (cur_wr_offset + sizeof(struct ath_pktlog_hdr)) > 116 log_buf->rd_offset) { 117 PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, 118 buf_size); 119 } 120 } else { 121 log_buf->rd_offset = cur_wr_offset; 122 } 123 124 log_hdr = (struct ath_pktlog_hdr *)(log_buf->log_data + cur_wr_offset); 125 126 log_hdr->flags = flags; 127 #ifdef HELIUMPLUS 128 log_hdr->macId = mac_id; 129 log_hdr->log_type = log_type; 130 #else 131 log_hdr->log_type = log_type; 132 #endif 133 log_hdr->size = (uint16_t) log_size; 134 log_hdr->missed_cnt = plarg->missed_cnt; 135 log_hdr->timestamp = plarg->timestamp; 136 pktlog_hdr_set_specific_data(log_hdr, 137 pktlog_arg_get_specific_data(plarg)); 138 cur_wr_offset += sizeof(*log_hdr); 139 140 if ((buf_size - cur_wr_offset) < log_size) { 141 while ((cur_wr_offset <= log_buf->rd_offset) 142 && (log_buf->rd_offset < buf_size)) { 143 PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, 144 buf_size); 145 } 146 cur_wr_offset = 0; 147 } 148 149 while ((cur_wr_offset <= log_buf->rd_offset) 150 && (cur_wr_offset + log_size) > log_buf->rd_offset) { 151 PKTLOG_MOV_RD_IDX(log_buf->rd_offset, log_buf, buf_size); 152 } 153 154 log_ptr = &(log_buf->log_data[cur_wr_offset]); 155 cur_wr_offset += log_hdr->size; 156 157 log_buf->wr_offset = ((buf_size - cur_wr_offset) >= 158 sizeof(struct ath_pktlog_hdr)) ? cur_wr_offset : 159 0; 160 161 plarg->buf = log_ptr; 162 } 163 164 char *pktlog_getbuf(struct pktlog_dev_t *pl_dev, 165 struct ath_pktlog_info *pl_info, 166 size_t log_size, struct ath_pktlog_hdr *pl_hdr) 167 { 168 struct ath_pktlog_arg plarg = { 0, }; 169 uint8_t flags = 0; 170 171 plarg.pl_info = pl_info; 172 #ifdef HELIUMPLUS 173 plarg.macId = pl_hdr->macId; 174 plarg.log_type = pl_hdr->log_type; 175 #else 176 plarg.log_type = pl_hdr->log_type; 177 #endif 178 plarg.log_size = log_size; 179 plarg.flags = pl_hdr->flags; 180 plarg.missed_cnt = pl_hdr->missed_cnt; 181 plarg.timestamp = pl_hdr->timestamp; 182 pktlog_arg_set_specific_data(&plarg, 183 pktlog_hdr_get_specific_data(pl_hdr)); 184 185 if (flags & PHFLAGS_INTERRUPT_CONTEXT) { 186 /* 187 * We are already in interrupt context, no need to make it 188 * intsafe. call the function directly. 189 */ 190 pktlog_getbuf_intsafe(&plarg); 191 } else { 192 PKTLOG_LOCK(pl_info); 193 pktlog_getbuf_intsafe(&plarg); 194 PKTLOG_UNLOCK(pl_info); 195 } 196 197 return plarg.buf; 198 } 199 #endif /*REMOVE_PKT_LOG */ 200