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
pktlog_hdr_set_specific_data(struct ath_pktlog_hdr * log_hdr,uint32_t type_specific_data)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
pktlog_hdr_get_specific_data(struct ath_pktlog_hdr * log_hdr)54 pktlog_hdr_get_specific_data(struct ath_pktlog_hdr *log_hdr)
55 {
56 	return log_hdr->type_specific_data;
57 }
58 
59 void
pktlog_arg_set_specific_data(struct ath_pktlog_arg * plarg,uint32_t type_specific_data)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
pktlog_arg_get_specific_data(struct ath_pktlog_arg * plarg)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 
pktlog_getbuf_intsafe(struct ath_pktlog_arg * plarg)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_info("Invalid parg");
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_info("Invalid log_buf");
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 
pktlog_getbuf(struct pktlog_dev_t * pl_dev,struct ath_pktlog_info * pl_info,size_t log_size,struct ath_pktlog_hdr * pl_hdr)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