blob: c20dd2e12160fa1736ea0ddeb50aa96c503aef6a [file] [log] [blame]
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/slab.h>
14#include <linux/delay.h>
15#include <linux/diagchar.h>
16#include <linux/kmemleak.h>
17#include <linux/workqueue.h>
18#include <linux/uaccess.h>
19#include "diagchar.h"
20#include "diagfwd_cntl.h"
21#include "diag_masks.h"
22#include "diagfwd_peripheral.h"
23#include "diag_ipc_logging.h"
24
25#define ALL_EQUIP_ID 100
26#define ALL_SSID -1
27
28#define DIAG_SET_FEATURE_MASK(x) (feature_bytes[(x)/8] |= (1 << (x & 0x7)))
29
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070030struct diag_mask_info msg_mask;
31struct diag_mask_info msg_bt_mask;
32struct diag_mask_info log_mask;
33struct diag_mask_info event_mask;
34
35static const struct diag_ssid_range_t msg_mask_tbl[] = {
36 { .ssid_first = MSG_SSID_0, .ssid_last = MSG_SSID_0_LAST },
37 { .ssid_first = MSG_SSID_1, .ssid_last = MSG_SSID_1_LAST },
38 { .ssid_first = MSG_SSID_2, .ssid_last = MSG_SSID_2_LAST },
39 { .ssid_first = MSG_SSID_3, .ssid_last = MSG_SSID_3_LAST },
40 { .ssid_first = MSG_SSID_4, .ssid_last = MSG_SSID_4_LAST },
41 { .ssid_first = MSG_SSID_5, .ssid_last = MSG_SSID_5_LAST },
42 { .ssid_first = MSG_SSID_6, .ssid_last = MSG_SSID_6_LAST },
43 { .ssid_first = MSG_SSID_7, .ssid_last = MSG_SSID_7_LAST },
44 { .ssid_first = MSG_SSID_8, .ssid_last = MSG_SSID_8_LAST },
45 { .ssid_first = MSG_SSID_9, .ssid_last = MSG_SSID_9_LAST },
46 { .ssid_first = MSG_SSID_10, .ssid_last = MSG_SSID_10_LAST },
47 { .ssid_first = MSG_SSID_11, .ssid_last = MSG_SSID_11_LAST },
48 { .ssid_first = MSG_SSID_12, .ssid_last = MSG_SSID_12_LAST },
49 { .ssid_first = MSG_SSID_13, .ssid_last = MSG_SSID_13_LAST },
50 { .ssid_first = MSG_SSID_14, .ssid_last = MSG_SSID_14_LAST },
51 { .ssid_first = MSG_SSID_15, .ssid_last = MSG_SSID_15_LAST },
52 { .ssid_first = MSG_SSID_16, .ssid_last = MSG_SSID_16_LAST },
53 { .ssid_first = MSG_SSID_17, .ssid_last = MSG_SSID_17_LAST },
54 { .ssid_first = MSG_SSID_18, .ssid_last = MSG_SSID_18_LAST },
55 { .ssid_first = MSG_SSID_19, .ssid_last = MSG_SSID_19_LAST },
56 { .ssid_first = MSG_SSID_20, .ssid_last = MSG_SSID_20_LAST },
57 { .ssid_first = MSG_SSID_21, .ssid_last = MSG_SSID_21_LAST },
58 { .ssid_first = MSG_SSID_22, .ssid_last = MSG_SSID_22_LAST },
59 { .ssid_first = MSG_SSID_23, .ssid_last = MSG_SSID_23_LAST },
Chris Lewd7316402017-06-19 15:42:50 -070060 { .ssid_first = MSG_SSID_24, .ssid_last = MSG_SSID_24_LAST },
61 { .ssid_first = MSG_SSID_25, .ssid_last = MSG_SSID_25_LAST }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070062};
63
Hardik Arya430b1e72018-04-09 14:49:40 +053064static int diag_check_update(int md_peripheral, int pid)
65{
66 int ret;
67 struct diag_md_session_t *info = NULL;
68
69 mutex_lock(&driver->md_session_lock);
70 info = diag_md_session_get_pid(pid);
71 ret = (!info || (info &&
72 (info->peripheral_mask & MD_PERIPHERAL_MASK(md_peripheral))));
73 mutex_unlock(&driver->md_session_lock);
74
75 return ret;
76}
77
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070078static int diag_apps_responds(void)
79{
80 /*
81 * Apps processor should respond to mask commands only if the
82 * Modem channel is up, the feature mask is received from Modem
83 * and if Modem supports Mask Centralization.
84 */
85 if (!chk_apps_only())
86 return 0;
87
88 if (driver->diagfwd_cntl[PERIPHERAL_MODEM] &&
89 driver->diagfwd_cntl[PERIPHERAL_MODEM]->ch_open &&
90 driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) {
91 if (driver->feature[PERIPHERAL_MODEM].mask_centralization)
92 return 1;
93 return 0;
94 }
95 return 1;
96}
97
98static void diag_send_log_mask_update(uint8_t peripheral, int equip_id)
99{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530100 int err = 0, send_once = 0, i;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700101 int header_len = sizeof(struct diag_ctrl_log_mask);
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530102 uint8_t *buf = NULL, *temp = NULL;
103 uint8_t upd = 0;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530104 uint32_t mask_size = 0, pd_mask = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700105 struct diag_ctrl_log_mask ctrl_pkt;
106 struct diag_mask_info *mask_info = NULL;
107 struct diag_log_mask_t *mask = NULL;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530108 struct diagfwd_info *fwd_info = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700109
110 if (peripheral >= NUM_PERIPHERALS)
111 return;
112
113 if (!driver->diagfwd_cntl[peripheral] ||
114 !driver->diagfwd_cntl[peripheral]->ch_open) {
115 pr_debug("diag: In %s, control channel is not open, p: %d\n",
116 __func__, peripheral);
117 return;
118 }
119
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530120 MD_PERIPHERAL_PD_MASK(TYPE_CNTL, peripheral, pd_mask);
121
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530122 if (driver->md_session_mask != 0) {
123 if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
124 if (driver->md_session_map[peripheral])
125 mask_info =
126 driver->md_session_map[peripheral]->log_mask;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530127 } else if (driver->md_session_mask & pd_mask) {
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530128 upd = diag_mask_to_pd_value(driver->md_session_mask);
129 if (upd && driver->md_session_map[upd])
130 mask_info =
131 driver->md_session_map[upd]->log_mask;
132 } else {
133 DIAG_LOG(DIAG_DEBUG_MASKS,
134 "asking for mask update with unknown session mask\n");
135 return;
136 }
137 } else {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700138 mask_info = &log_mask;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530139 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700140
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530141 if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700142 return;
143
144 mask = (struct diag_log_mask_t *)mask_info->ptr;
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530145 if (!mask->ptr)
146 return;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700147 buf = mask_info->update_buf;
148
149 switch (mask_info->status) {
150 case DIAG_CTRL_MASK_ALL_DISABLED:
151 ctrl_pkt.equip_id = 0;
152 ctrl_pkt.num_items = 0;
153 ctrl_pkt.log_mask_size = 0;
154 send_once = 1;
155 break;
156 case DIAG_CTRL_MASK_ALL_ENABLED:
157 ctrl_pkt.equip_id = 0;
158 ctrl_pkt.num_items = 0;
159 ctrl_pkt.log_mask_size = 0;
160 send_once = 1;
161 break;
162 case DIAG_CTRL_MASK_VALID:
163 send_once = 0;
164 break;
165 default:
166 pr_debug("diag: In %s, invalid log_mask status\n", __func__);
167 return;
168 }
169
170 mutex_lock(&mask_info->lock);
171 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
172 if (equip_id != i && equip_id != ALL_EQUIP_ID)
173 continue;
174
175 mutex_lock(&mask->lock);
176 ctrl_pkt.cmd_type = DIAG_CTRL_MSG_LOG_MASK;
177 ctrl_pkt.stream_id = 1;
178 ctrl_pkt.status = mask_info->status;
179 if (mask_info->status == DIAG_CTRL_MASK_VALID) {
180 mask_size = LOG_ITEMS_TO_SIZE(mask->num_items_tools);
181 ctrl_pkt.equip_id = i;
182 ctrl_pkt.num_items = mask->num_items_tools;
183 ctrl_pkt.log_mask_size = mask_size;
184 }
185 ctrl_pkt.data_len = LOG_MASK_CTRL_HEADER_LEN + mask_size;
186
187 if (header_len + mask_size > mask_info->update_buf_len) {
188 temp = krealloc(buf, header_len + mask_size,
189 GFP_KERNEL);
190 if (!temp) {
191 pr_err_ratelimited("diag: Unable to realloc log update buffer, new size: %d, equip_id: %d\n",
192 header_len + mask_size, equip_id);
193 mutex_unlock(&mask->lock);
194 break;
195 }
196 mask_info->update_buf = temp;
197 mask_info->update_buf_len = header_len + mask_size;
198 }
199
200 memcpy(buf, &ctrl_pkt, header_len);
201 if (mask_size > 0)
202 memcpy(buf + header_len, mask->ptr, mask_size);
203 mutex_unlock(&mask->lock);
204
205 DIAG_LOG(DIAG_DEBUG_MASKS,
206 "sending ctrl pkt to %d, e %d num_items %d size %d\n",
207 peripheral, i, ctrl_pkt.num_items,
208 ctrl_pkt.log_mask_size);
209
210 err = diagfwd_write(peripheral, TYPE_CNTL,
211 buf, header_len + mask_size);
212 if (err && err != -ENODEV)
213 pr_err_ratelimited("diag: Unable to send log masks to peripheral %d, equip_id: %d, err: %d\n",
214 peripheral, i, err);
215 if (send_once || equip_id != ALL_EQUIP_ID)
216 break;
217
218 }
219 mutex_unlock(&mask_info->lock);
220}
221
222static void diag_send_event_mask_update(uint8_t peripheral)
223{
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530224 uint8_t *buf = NULL, *temp = NULL;
225 uint8_t upd = 0;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530226 uint32_t pd_mask = 0;
227 int num_bytes = EVENT_COUNT_TO_BYTES(driver->last_event_id);
228 int write_len = 0, err = 0, i = 0, temp_len = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700229 struct diag_ctrl_event_mask header;
230 struct diag_mask_info *mask_info = NULL;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530231 struct diagfwd_info *fwd_info = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700232
233 if (num_bytes <= 0 || num_bytes > driver->event_mask_size) {
234 pr_debug("diag: In %s, invalid event mask length %d\n",
235 __func__, num_bytes);
236 return;
237 }
238
239 if (peripheral >= NUM_PERIPHERALS)
240 return;
241
242 if (!driver->diagfwd_cntl[peripheral] ||
243 !driver->diagfwd_cntl[peripheral]->ch_open) {
244 pr_debug("diag: In %s, control channel is not open, p: %d\n",
245 __func__, peripheral);
246 return;
247 }
248
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530249 MD_PERIPHERAL_PD_MASK(TYPE_CNTL, peripheral, pd_mask);
250
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530251 if (driver->md_session_mask != 0) {
252 if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
253 if (driver->md_session_map[peripheral])
254 mask_info =
255 driver->md_session_map[peripheral]->event_mask;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530256 } else if (driver->md_session_mask & pd_mask) {
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530257 upd = diag_mask_to_pd_value(driver->md_session_mask);
258 if (upd && driver->md_session_map[upd])
259 mask_info =
260 driver->md_session_map[upd]->event_mask;
261 } else {
262 DIAG_LOG(DIAG_DEBUG_MASKS,
263 "asking for mask update with unknown session mask\n");
264 return;
265 }
266 } else {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700267 mask_info = &event_mask;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530268 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700269
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530270 if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700271 return;
272
273 buf = mask_info->update_buf;
274 mutex_lock(&mask_info->lock);
275 header.cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
276 header.stream_id = 1;
277 header.status = mask_info->status;
278
279 switch (mask_info->status) {
280 case DIAG_CTRL_MASK_ALL_DISABLED:
281 header.event_config = 0;
282 header.event_mask_size = 0;
283 break;
284 case DIAG_CTRL_MASK_ALL_ENABLED:
285 header.event_config = 1;
286 header.event_mask_size = 0;
287 break;
288 case DIAG_CTRL_MASK_VALID:
289 header.event_config = 1;
290 header.event_mask_size = num_bytes;
291 if (num_bytes + sizeof(header) > mask_info->update_buf_len) {
292 temp_len = num_bytes + sizeof(header);
293 temp = krealloc(buf, temp_len, GFP_KERNEL);
294 if (!temp) {
295 pr_err("diag: Unable to realloc event mask update buffer\n");
296 goto err;
297 } else {
298 mask_info->update_buf = temp;
299 mask_info->update_buf_len = temp_len;
300 }
301 }
302 memcpy(buf + sizeof(header), mask_info->ptr, num_bytes);
303 write_len += num_bytes;
304 break;
305 default:
306 pr_debug("diag: In %s, invalid status %d\n", __func__,
307 mask_info->status);
308 goto err;
309 }
310 header.data_len = EVENT_MASK_CTRL_HEADER_LEN + header.event_mask_size;
311 memcpy(buf, &header, sizeof(header));
312 write_len += sizeof(header);
313
314 err = diagfwd_write(peripheral, TYPE_CNTL, buf, write_len);
315 if (err && err != -ENODEV)
316 pr_err_ratelimited("diag: Unable to send event masks to peripheral %d\n",
317 peripheral);
318err:
319 mutex_unlock(&mask_info->lock);
320}
321
322static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)
323{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530324 int i, err = 0, temp_len = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700325 int header_len = sizeof(struct diag_ctrl_msg_mask);
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530326 uint8_t *buf = NULL, *temp = NULL;
327 uint8_t upd = 0;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530328 uint8_t msg_mask_tbl_count_local;
329 uint32_t mask_size = 0, pd_mask = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700330 struct diag_mask_info *mask_info = NULL;
331 struct diag_msg_mask_t *mask = NULL;
332 struct diag_ctrl_msg_mask header;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530333 struct diagfwd_info *fwd_info = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700334
335 if (peripheral >= NUM_PERIPHERALS)
336 return;
337
338 if (!driver->diagfwd_cntl[peripheral] ||
339 !driver->diagfwd_cntl[peripheral]->ch_open) {
340 pr_debug("diag: In %s, control channel is not open, p: %d\n",
341 __func__, peripheral);
342 return;
343 }
344
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530345 MD_PERIPHERAL_PD_MASK(TYPE_CNTL, peripheral, pd_mask);
346
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530347 if (driver->md_session_mask != 0) {
348 if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
349 if (driver->md_session_map[peripheral])
350 mask_info =
351 driver->md_session_map[peripheral]->msg_mask;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530352 } else if (driver->md_session_mask & pd_mask) {
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530353 upd = diag_mask_to_pd_value(driver->md_session_mask);
354 if (upd && driver->md_session_map[upd])
355 mask_info =
356 driver->md_session_map[upd]->msg_mask;
357 } else {
358 DIAG_LOG(DIAG_DEBUG_MASKS,
359 "asking for mask update with unknown session mask\n");
360 return;
361 }
362 } else {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700363 mask_info = &msg_mask;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530364 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700365
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530366 if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700367 return;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530368 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700369 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530370 if (!mask->ptr) {
371 mutex_unlock(&driver->msg_mask_lock);
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530372 return;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530373 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700374 buf = mask_info->update_buf;
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530375 msg_mask_tbl_count_local = driver->msg_mask_tbl_count;
376 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700377 mutex_lock(&mask_info->lock);
378 switch (mask_info->status) {
379 case DIAG_CTRL_MASK_ALL_DISABLED:
380 mask_size = 0;
381 break;
382 case DIAG_CTRL_MASK_ALL_ENABLED:
383 mask_size = 1;
384 break;
385 case DIAG_CTRL_MASK_VALID:
386 break;
387 default:
388 pr_debug("diag: In %s, invalid status: %d\n", __func__,
389 mask_info->status);
390 goto err;
391 }
392
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530393 for (i = 0; i < msg_mask_tbl_count_local; i++, mask++) {
394 mutex_lock(&driver->msg_mask_lock);
395 if (((mask->ssid_first > first) ||
396 (mask->ssid_last_tools < last)) && first != ALL_SSID) {
397 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700398 continue;
399 }
400
401 mutex_lock(&mask->lock);
402 if (mask_info->status == DIAG_CTRL_MASK_VALID) {
403 mask_size =
404 mask->ssid_last_tools - mask->ssid_first + 1;
405 temp_len = mask_size * sizeof(uint32_t);
406 if (temp_len + header_len <= mask_info->update_buf_len)
407 goto proceed;
408 temp = krealloc(mask_info->update_buf, temp_len,
409 GFP_KERNEL);
410 if (!temp) {
411 pr_err("diag: In %s, unable to realloc msg_mask update buffer\n",
412 __func__);
413 mask_size = (mask_info->update_buf_len -
414 header_len) / sizeof(uint32_t);
415 } else {
416 mask_info->update_buf = temp;
417 mask_info->update_buf_len = temp_len;
418 pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n",
419 __func__, mask_info->update_buf_len);
420 }
421 } else if (mask_info->status == DIAG_CTRL_MASK_ALL_ENABLED) {
422 mask_size = 1;
423 }
424proceed:
425 header.cmd_type = DIAG_CTRL_MSG_F3_MASK;
426 header.status = mask_info->status;
427 header.stream_id = 1;
428 header.msg_mode = 0;
429 header.ssid_first = mask->ssid_first;
430 header.ssid_last = mask->ssid_last_tools;
431 header.msg_mask_size = mask_size;
432 mask_size *= sizeof(uint32_t);
433 header.data_len = MSG_MASK_CTRL_HEADER_LEN + mask_size;
434 memcpy(buf, &header, header_len);
435 if (mask_size > 0)
436 memcpy(buf + header_len, mask->ptr, mask_size);
437 mutex_unlock(&mask->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530438 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700439
440 err = diagfwd_write(peripheral, TYPE_CNTL, buf,
441 header_len + mask_size);
442 if (err && err != -ENODEV)
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530443 pr_err_ratelimited("diag: Unable to send msg masks to peripheral %d, error = %d\n",
444 peripheral, err);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700445
446 if (first != ALL_SSID)
447 break;
448 }
449err:
450 mutex_unlock(&mask_info->lock);
451}
452
453static void diag_send_time_sync_update(uint8_t peripheral)
454{
455 struct diag_ctrl_msg_time_sync time_sync_msg;
456 int msg_size = sizeof(struct diag_ctrl_msg_time_sync);
457 int err = 0;
458
459 if (peripheral >= NUM_PERIPHERALS) {
460 pr_err("diag: In %s, Invalid peripheral, %d\n",
461 __func__, peripheral);
462 return;
463 }
464
465 if (!driver->diagfwd_cntl[peripheral] ||
466 !driver->diagfwd_cntl[peripheral]->ch_open) {
467 pr_err("diag: In %s, control channel is not open, p: %d, %pK\n",
468 __func__, peripheral, driver->diagfwd_cntl[peripheral]);
469 return;
470 }
471
472 mutex_lock(&driver->diag_cntl_mutex);
473 time_sync_msg.ctrl_pkt_id = DIAG_CTRL_MSG_TIME_SYNC_PKT;
474 time_sync_msg.ctrl_pkt_data_len = 5;
475 time_sync_msg.version = 1;
476 time_sync_msg.time_api = driver->uses_time_api;
477
478 err = diagfwd_write(peripheral, TYPE_CNTL, &time_sync_msg, msg_size);
479 if (err)
480 pr_err("diag: In %s, unable to write to peripheral: %d, type: %d, len: %d, err: %d\n",
481 __func__, peripheral, TYPE_CNTL,
482 msg_size, err);
483 mutex_unlock(&driver->diag_cntl_mutex);
484}
485
486static void diag_send_feature_mask_update(uint8_t peripheral)
487{
488 void *buf = driver->buf_feature_mask_update;
489 int header_size = sizeof(struct diag_ctrl_feature_mask);
490 uint8_t feature_bytes[FEATURE_MASK_LEN] = {0, 0};
491 struct diag_ctrl_feature_mask feature_mask;
492 int total_len = 0;
493 int err = 0;
494
495 if (peripheral >= NUM_PERIPHERALS) {
496 pr_err("diag: In %s, Invalid peripheral, %d\n",
497 __func__, peripheral);
498 return;
499 }
500
501 if (!driver->diagfwd_cntl[peripheral] ||
502 !driver->diagfwd_cntl[peripheral]->ch_open) {
503 pr_err("diag: In %s, control channel is not open, p: %d, %pK\n",
504 __func__, peripheral, driver->diagfwd_cntl[peripheral]);
505 return;
506 }
507
508 mutex_lock(&driver->diag_cntl_mutex);
509 /* send feature mask update */
510 feature_mask.ctrl_pkt_id = DIAG_CTRL_MSG_FEATURE;
511 feature_mask.ctrl_pkt_data_len = sizeof(uint32_t) + FEATURE_MASK_LEN;
512 feature_mask.feature_mask_len = FEATURE_MASK_LEN;
513 memcpy(buf, &feature_mask, header_size);
514 DIAG_SET_FEATURE_MASK(F_DIAG_FEATURE_MASK_SUPPORT);
515 DIAG_SET_FEATURE_MASK(F_DIAG_LOG_ON_DEMAND_APPS);
516 DIAG_SET_FEATURE_MASK(F_DIAG_STM);
517 DIAG_SET_FEATURE_MASK(F_DIAG_DCI_EXTENDED_HEADER_SUPPORT);
Sreelakshmi Gownipalli8d477d32017-02-08 19:49:06 -0800518 DIAG_SET_FEATURE_MASK(F_DIAG_DIAGID_SUPPORT);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700519 if (driver->supports_separate_cmdrsp)
520 DIAG_SET_FEATURE_MASK(F_DIAG_REQ_RSP_SUPPORT);
521 if (driver->supports_apps_hdlc_encoding)
522 DIAG_SET_FEATURE_MASK(F_DIAG_APPS_HDLC_ENCODE);
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530523 if (driver->supports_apps_header_untagging) {
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530524 if (driver->feature[peripheral].untag_header) {
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530525 DIAG_SET_FEATURE_MASK(F_DIAG_PKT_HEADER_UNTAG);
526 driver->peripheral_untag[peripheral] =
527 ENABLE_PKT_HEADER_UNTAGGING;
528 }
529 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700530 DIAG_SET_FEATURE_MASK(F_DIAG_MASK_CENTRALIZATION);
531 if (driver->supports_sockets)
532 DIAG_SET_FEATURE_MASK(F_DIAG_SOCKETS_ENABLED);
533
534 memcpy(buf + header_size, &feature_bytes, FEATURE_MASK_LEN);
535 total_len = header_size + FEATURE_MASK_LEN;
536
537 err = diagfwd_write(peripheral, TYPE_CNTL, buf, total_len);
538 if (err) {
539 pr_err_ratelimited("diag: In %s, unable to write feature mask to peripheral: %d, type: %d, len: %d, err: %d\n",
540 __func__, peripheral, TYPE_CNTL,
541 total_len, err);
542 mutex_unlock(&driver->diag_cntl_mutex);
543 return;
544 }
545 driver->feature[peripheral].sent_feature_mask = 1;
546 mutex_unlock(&driver->diag_cntl_mutex);
547}
548
549static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530550 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700551{
552 int i;
553 int write_len = 0;
554 struct diag_msg_mask_t *mask_ptr = NULL;
555 struct diag_msg_ssid_query_t rsp;
556 struct diag_ssid_range_t ssid_range;
557 struct diag_mask_info *mask_info = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530558 struct diag_md_session_t *info = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700559
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530560 mutex_lock(&driver->md_session_lock);
561 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700562 mask_info = (!info) ? &msg_mask : info->msg_mask;
563 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
564 !mask_info) {
565 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
566 __func__, src_buf, src_len, dest_buf, dest_len,
567 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530568 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700569 return -EINVAL;
570 }
Hardik Arya3d3436a2017-09-11 11:37:33 +0530571 if (!mask_info->ptr) {
572 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
573 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530574 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530575 return -EINVAL;
576 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700577
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530578 if (!diag_apps_responds()) {
579 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700580 return 0;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530581 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530582 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700583 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
584 rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
585 rsp.status = MSG_STATUS_SUCCESS;
586 rsp.padding = 0;
587 rsp.count = driver->msg_mask_tbl_count;
588 memcpy(dest_buf, &rsp, sizeof(rsp));
589 write_len += sizeof(rsp);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700590 mask_ptr = (struct diag_msg_mask_t *)mask_info->ptr;
591 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask_ptr++) {
592 if (write_len + sizeof(ssid_range) > dest_len) {
593 pr_err("diag: In %s, Truncating response due to size limitations of rsp buffer\n",
594 __func__);
595 break;
596 }
597 ssid_range.ssid_first = mask_ptr->ssid_first;
598 ssid_range.ssid_last = mask_ptr->ssid_last_tools;
599 memcpy(dest_buf + write_len, &ssid_range, sizeof(ssid_range));
600 write_len += sizeof(ssid_range);
601 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530602 mutex_unlock(&driver->msg_mask_lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530603 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700604 return write_len;
605}
606
607static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530608 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700609{
610 int i = 0;
611 int write_len = 0;
612 int num_entries = 0;
613 int copy_len = 0;
614 struct diag_msg_mask_t *build_mask = NULL;
615 struct diag_build_mask_req_t *req = NULL;
616 struct diag_msg_build_mask_t rsp;
617
618 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
619 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
620 __func__, src_buf, src_len, dest_buf, dest_len);
621 return -EINVAL;
622 }
623
624 if (!diag_apps_responds())
625 return 0;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530626 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700627 req = (struct diag_build_mask_req_t *)src_buf;
628 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
629 rsp.sub_cmd = DIAG_CMD_OP_GET_BUILD_MASK;
630 rsp.ssid_first = req->ssid_first;
631 rsp.ssid_last = req->ssid_last;
632 rsp.status = MSG_STATUS_FAIL;
633 rsp.padding = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700634 build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530635 for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700636 if (build_mask->ssid_first != req->ssid_first)
637 continue;
638 num_entries = req->ssid_last - req->ssid_first + 1;
639 if (num_entries > build_mask->range) {
640 pr_warn("diag: In %s, truncating ssid range for ssid_first: %d ssid_last %d\n",
641 __func__, req->ssid_first, req->ssid_last);
642 num_entries = build_mask->range;
643 req->ssid_last = req->ssid_first + build_mask->range;
644 }
645 copy_len = num_entries * sizeof(uint32_t);
646 if (copy_len + sizeof(rsp) > dest_len)
647 copy_len = dest_len - sizeof(rsp);
648 memcpy(dest_buf + sizeof(rsp), build_mask->ptr, copy_len);
649 write_len += copy_len;
650 rsp.ssid_last = build_mask->ssid_last;
651 rsp.status = MSG_STATUS_SUCCESS;
652 break;
653 }
654 memcpy(dest_buf, &rsp, sizeof(rsp));
655 write_len += sizeof(rsp);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530656 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700657 return write_len;
658}
659
660static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530661 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700662{
663 int i;
664 int write_len = 0;
665 uint32_t mask_size = 0;
666 struct diag_msg_mask_t *mask = NULL;
667 struct diag_build_mask_req_t *req = NULL;
668 struct diag_msg_build_mask_t rsp;
669 struct diag_mask_info *mask_info = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530670 struct diag_md_session_t *info = NULL;
671
672 mutex_lock(&driver->md_session_lock);
673 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700674
675 mask_info = (!info) ? &msg_mask : info->msg_mask;
676 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
677 !mask_info) {
678 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
679 __func__, src_buf, src_len, dest_buf, dest_len,
680 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530681 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700682 return -EINVAL;
683 }
Hardik Arya3d3436a2017-09-11 11:37:33 +0530684 if (!mask_info->ptr) {
685 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
686 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530687 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530688 return -EINVAL;
689 }
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530690 if (!diag_apps_responds()) {
691 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700692 return 0;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530693 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700694
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530695 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700696 req = (struct diag_build_mask_req_t *)src_buf;
697 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
698 rsp.sub_cmd = DIAG_CMD_OP_GET_MSG_MASK;
699 rsp.ssid_first = req->ssid_first;
700 rsp.ssid_last = req->ssid_last;
701 rsp.status = MSG_STATUS_FAIL;
702 rsp.padding = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700703 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +0530704 if (!mask->ptr) {
705 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
706 __func__, mask->ptr);
707 mutex_unlock(&driver->msg_mask_lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530708 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530709 return -EINVAL;
710 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700711 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
712 if ((req->ssid_first < mask->ssid_first) ||
713 (req->ssid_first > mask->ssid_last_tools)) {
714 continue;
715 }
716 mask_size = mask->range * sizeof(uint32_t);
717 /* Copy msg mask only till the end of the rsp buffer */
718 if (mask_size + sizeof(rsp) > dest_len)
719 mask_size = dest_len - sizeof(rsp);
720 memcpy(dest_buf + sizeof(rsp), mask->ptr, mask_size);
721 write_len += mask_size;
722 rsp.status = MSG_STATUS_SUCCESS;
723 break;
724 }
725 memcpy(dest_buf, &rsp, sizeof(rsp));
726 write_len += sizeof(rsp);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530727 mutex_unlock(&driver->msg_mask_lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530728 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700729 return write_len;
730}
731
732static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530733 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700734{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530735 uint32_t mask_size = 0, offset = 0;
736 uint32_t *temp = NULL;
737 int write_len = 0, i = 0, found = 0, peripheral;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700738 int header_len = sizeof(struct diag_msg_build_mask_t);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700739 struct diag_msg_mask_t *mask = NULL;
740 struct diag_msg_build_mask_t *req = NULL;
741 struct diag_msg_build_mask_t rsp;
742 struct diag_mask_info *mask_info = NULL;
743 struct diag_msg_mask_t *mask_next = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530744 struct diag_md_session_t *info = NULL;
745
746 mutex_lock(&driver->md_session_lock);
747 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700748
749 mask_info = (!info) ? &msg_mask : info->msg_mask;
750 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
751 !mask_info) {
752 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
753 __func__, src_buf, src_len, dest_buf, dest_len,
754 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530755 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700756 return -EINVAL;
757 }
Hardik Arya3d3436a2017-09-11 11:37:33 +0530758 if (!mask_info->ptr) {
759 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
760 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530761 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530762 return -EINVAL;
763 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700764
765 req = (struct diag_msg_build_mask_t *)src_buf;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700766 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530767 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700768 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +0530769 if (!mask->ptr) {
770 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
771 __func__, mask->ptr);
772 mutex_unlock(&driver->msg_mask_lock);
773 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530774 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530775 return -EINVAL;
776 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700777 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
778 if (i < (driver->msg_mask_tbl_count - 1)) {
779 mask_next = mask;
780 mask_next++;
781 } else
782 mask_next = NULL;
783
784 if ((req->ssid_first < mask->ssid_first) ||
785 (req->ssid_first > mask->ssid_first + MAX_SSID_PER_RANGE) ||
786 (mask_next && (req->ssid_first >= mask_next->ssid_first))) {
787 continue;
788 }
789 mask_next = NULL;
790 found = 1;
791 mutex_lock(&mask->lock);
792 mask_size = req->ssid_last - req->ssid_first + 1;
793 if (mask_size > MAX_SSID_PER_RANGE) {
794 pr_warn("diag: In %s, truncating ssid range, %d-%d to max allowed: %d\n",
795 __func__, mask->ssid_first, mask->ssid_last,
796 MAX_SSID_PER_RANGE);
797 mask_size = MAX_SSID_PER_RANGE;
798 mask->range_tools = MAX_SSID_PER_RANGE;
799 mask->ssid_last_tools =
800 mask->ssid_first + mask->range_tools;
801 }
802 if (req->ssid_last > mask->ssid_last_tools) {
803 pr_debug("diag: Msg SSID range mismatch\n");
804 if (mask_size != MAX_SSID_PER_RANGE)
805 mask->ssid_last_tools = req->ssid_last;
806 mask->range_tools =
807 mask->ssid_last_tools - mask->ssid_first + 1;
808 temp = krealloc(mask->ptr,
809 mask->range_tools * sizeof(uint32_t),
810 GFP_KERNEL);
811 if (!temp) {
812 pr_err_ratelimited("diag: In %s, unable to allocate memory for msg mask ptr, mask_size: %d\n",
813 __func__, mask_size);
814 mutex_unlock(&mask->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530815 mutex_unlock(&driver->msg_mask_lock);
816 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530817 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700818 return -ENOMEM;
819 }
820 mask->ptr = temp;
821 }
822
823 offset = req->ssid_first - mask->ssid_first;
824 if (offset + mask_size > mask->range_tools) {
825 pr_err("diag: In %s, Not in msg mask range, mask_size: %d, offset: %d\n",
826 __func__, mask_size, offset);
827 mutex_unlock(&mask->lock);
828 break;
829 }
830 mask_size = mask_size * sizeof(uint32_t);
831 memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
832 mutex_unlock(&mask->lock);
833 mask_info->status = DIAG_CTRL_MASK_VALID;
834 break;
835 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530836 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530837 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530838 mutex_unlock(&driver->md_session_lock);
Hardik Arya430b1e72018-04-09 14:49:40 +0530839 if (diag_check_update(APPS_DATA, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700840 diag_update_userspace_clients(MSG_MASKS_TYPE);
841
842 /*
843 * Apps processor must send the response to this command. Frame the
844 * response.
845 */
846 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
847 rsp.sub_cmd = DIAG_CMD_OP_SET_MSG_MASK;
848 rsp.ssid_first = req->ssid_first;
849 rsp.ssid_last = req->ssid_last;
850 rsp.status = found;
851 rsp.padding = 0;
852 memcpy(dest_buf, &rsp, header_len);
853 write_len += header_len;
854 if (!found)
855 goto end;
856 if (mask_size + write_len > dest_len)
857 mask_size = dest_len - write_len;
858 memcpy(dest_buf + write_len, src_buf + header_len, mask_size);
859 write_len += mask_size;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530860 for (i = 0; i < NUM_MD_SESSIONS; i++) {
861 if (i == APPS_DATA)
862 continue;
Hardik Arya430b1e72018-04-09 14:49:40 +0530863 if (!diag_check_update(i, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700864 continue;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530865 if (i > NUM_PERIPHERALS)
866 peripheral = diag_search_peripheral_by_pd(i);
867 else
868 peripheral = i;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530869 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530870 diag_send_msg_mask_update(peripheral, req->ssid_first,
871 req->ssid_last);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530872 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700873 }
874end:
875 return write_len;
876}
877
878static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530879 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700880{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530881 int i, write_len = 0, peripheral;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700882 int header_len = sizeof(struct diag_msg_config_rsp_t);
883 struct diag_msg_config_rsp_t rsp;
884 struct diag_msg_config_rsp_t *req = NULL;
885 struct diag_msg_mask_t *mask = NULL;
886 struct diag_mask_info *mask_info = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530887 struct diag_md_session_t *info = NULL;
888
889 mutex_lock(&driver->md_session_lock);
890 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700891
892 mask_info = (!info) ? &msg_mask : info->msg_mask;
893 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
894 !mask_info) {
895 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
896 __func__, src_buf, src_len, dest_buf, dest_len,
897 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530898 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700899 return -EINVAL;
900 }
Hardik Arya3d3436a2017-09-11 11:37:33 +0530901 if (!mask_info->ptr) {
902 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
903 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530904 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530905 return -EINVAL;
906 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700907
908 req = (struct diag_msg_config_rsp_t *)src_buf;
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530909
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700910 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530911 mutex_lock(&driver->msg_mask_lock);
912
913 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +0530914 if (!mask->ptr) {
915 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
916 __func__, mask->ptr);
917 mutex_unlock(&driver->msg_mask_lock);
918 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530919 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +0530920 return -EINVAL;
921 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700922 mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
923 DIAG_CTRL_MASK_ALL_DISABLED;
924 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
925 mutex_lock(&mask->lock);
926 memset(mask->ptr, req->rt_mask,
927 mask->range * sizeof(uint32_t));
928 mutex_unlock(&mask->lock);
929 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530930 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530931 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530932 mutex_unlock(&driver->md_session_lock);
Hardik Arya430b1e72018-04-09 14:49:40 +0530933 if (diag_check_update(APPS_DATA, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700934 diag_update_userspace_clients(MSG_MASKS_TYPE);
935
936 /*
937 * Apps processor must send the response to this command. Frame the
938 * response.
939 */
940 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
941 rsp.sub_cmd = DIAG_CMD_OP_SET_ALL_MSG_MASK;
942 rsp.status = MSG_STATUS_SUCCESS;
943 rsp.padding = 0;
944 rsp.rt_mask = req->rt_mask;
945 memcpy(dest_buf, &rsp, header_len);
946 write_len += header_len;
947
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530948 for (i = 0; i < NUM_MD_SESSIONS; i++) {
949 if (i == APPS_DATA)
950 continue;
Hardik Arya430b1e72018-04-09 14:49:40 +0530951 if (!diag_check_update(i, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700952 continue;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530953 if (i > NUM_PERIPHERALS)
954 peripheral = diag_search_peripheral_by_pd(i);
955 else
956 peripheral = i;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530957 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +0530958 diag_send_msg_mask_update(peripheral, ALL_SSID, ALL_SSID);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530959 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700960 }
961
962 return write_len;
963}
964
965static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +0530966 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700967{
968 int write_len = 0;
969 uint32_t mask_size;
970 struct diag_event_mask_config_t rsp;
971
972 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
973 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
974 __func__, src_buf, src_len, dest_buf, dest_len);
975 return -EINVAL;
976 }
977
978 if (!diag_apps_responds())
979 return 0;
980
981 mask_size = EVENT_COUNT_TO_BYTES(driver->last_event_id);
982 if (mask_size + sizeof(rsp) > dest_len) {
983 pr_err("diag: In %s, invalid mask size: %d\n", __func__,
984 mask_size);
985 return -ENOMEM;
986 }
987
988 rsp.cmd_code = DIAG_CMD_GET_EVENT_MASK;
989 rsp.status = EVENT_STATUS_SUCCESS;
990 rsp.padding = 0;
991 rsp.num_bits = driver->last_event_id + 1;
992 memcpy(dest_buf, &rsp, sizeof(rsp));
993 write_len += sizeof(rsp);
994 memcpy(dest_buf + write_len, event_mask.ptr, mask_size);
995 write_len += mask_size;
996
997 return write_len;
998}
999
1000static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301001 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001002{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301003 int i, write_len = 0, mask_len = 0, peripheral;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001004 int header_len = sizeof(struct diag_event_mask_config_t);
1005 struct diag_event_mask_config_t rsp;
1006 struct diag_event_mask_config_t *req;
1007 struct diag_mask_info *mask_info = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301008 struct diag_md_session_t *info = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001009
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301010 mutex_lock(&driver->md_session_lock);
1011 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001012 mask_info = (!info) ? &event_mask : info->event_mask;
1013 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1014 !mask_info) {
1015 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1016 __func__, src_buf, src_len, dest_buf, dest_len,
1017 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301018 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001019 return -EINVAL;
1020 }
Hardik Arya3d3436a2017-09-11 11:37:33 +05301021 if (!mask_info->ptr) {
1022 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
1023 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301024 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301025 return -EINVAL;
1026 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001027 req = (struct diag_event_mask_config_t *)src_buf;
1028 mask_len = EVENT_COUNT_TO_BYTES(req->num_bits);
1029 if (mask_len <= 0 || mask_len > event_mask.mask_len) {
1030 pr_err("diag: In %s, invalid event mask len: %d\n", __func__,
1031 mask_len);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301032 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001033 return -EIO;
1034 }
1035
1036 mutex_lock(&mask_info->lock);
1037 memcpy(mask_info->ptr, src_buf + header_len, mask_len);
1038 mask_info->status = DIAG_CTRL_MASK_VALID;
1039 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301040 mutex_unlock(&driver->md_session_lock);
Hardik Arya430b1e72018-04-09 14:49:40 +05301041 if (diag_check_update(APPS_DATA, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001042 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1043
1044 /*
1045 * Apps processor must send the response to this command. Frame the
1046 * response.
1047 */
1048 rsp.cmd_code = DIAG_CMD_SET_EVENT_MASK;
1049 rsp.status = EVENT_STATUS_SUCCESS;
1050 rsp.padding = 0;
1051 rsp.num_bits = driver->last_event_id + 1;
1052 memcpy(dest_buf, &rsp, header_len);
1053 write_len += header_len;
1054 memcpy(dest_buf + write_len, mask_info->ptr, mask_len);
1055 write_len += mask_len;
1056
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301057 for (i = 0; i < NUM_MD_SESSIONS; i++) {
1058 if (i == APPS_DATA)
1059 continue;
Hardik Arya430b1e72018-04-09 14:49:40 +05301060 if (!diag_check_update(i, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001061 continue;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301062 if (i > NUM_PERIPHERALS)
1063 peripheral = diag_search_peripheral_by_pd(i);
1064 else
1065 peripheral = i;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301066 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301067 diag_send_event_mask_update(peripheral);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301068 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001069 }
1070
1071 return write_len;
1072}
1073
1074static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301075 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001076{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301077 int write_len = 0, i, peripheral;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001078 uint8_t toggle = 0;
1079 struct diag_event_report_t header;
1080 struct diag_mask_info *mask_info = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301081 struct diag_md_session_t *info = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001082
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301083 mutex_lock(&driver->md_session_lock);
1084 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001085 mask_info = (!info) ? &event_mask : info->event_mask;
1086 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1087 !mask_info) {
1088 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1089 __func__, src_buf, src_len, dest_buf, dest_len,
1090 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301091 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001092 return -EINVAL;
1093 }
Hardik Arya3d3436a2017-09-11 11:37:33 +05301094 if (!mask_info->ptr) {
1095 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
1096 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301097 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301098 return -EINVAL;
1099 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001100
1101 toggle = *(src_buf + 1);
1102 mutex_lock(&mask_info->lock);
1103 if (toggle) {
1104 mask_info->status = DIAG_CTRL_MASK_ALL_ENABLED;
1105 memset(mask_info->ptr, 0xFF, mask_info->mask_len);
1106 } else {
1107 mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
1108 memset(mask_info->ptr, 0, mask_info->mask_len);
1109 }
1110 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301111 mutex_unlock(&driver->md_session_lock);
Hardik Arya430b1e72018-04-09 14:49:40 +05301112 if (diag_check_update(APPS_DATA, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001113 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1114
1115 /*
1116 * Apps processor must send the response to this command. Frame the
1117 * response.
1118 */
1119 header.cmd_code = DIAG_CMD_EVENT_TOGGLE;
1120 header.padding = 0;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301121 for (i = 0; i < NUM_MD_SESSIONS; i++) {
1122 if (i == APPS_DATA)
1123 continue;
Hardik Arya430b1e72018-04-09 14:49:40 +05301124 if (!diag_check_update(i, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001125 continue;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301126 if (i > NUM_PERIPHERALS)
1127 peripheral = diag_search_peripheral_by_pd(i);
1128 else
1129 peripheral = i;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301130 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301131 diag_send_event_mask_update(peripheral);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301132 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001133 }
1134 memcpy(dest_buf, &header, sizeof(header));
1135 write_len += sizeof(header);
1136
1137 return write_len;
1138}
1139
1140static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301141 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001142{
1143 int i;
1144 int status = LOG_STATUS_INVALID;
1145 int write_len = 0;
1146 int read_len = 0;
1147 int req_header_len = sizeof(struct diag_log_config_req_t);
1148 int rsp_header_len = sizeof(struct diag_log_config_rsp_t);
1149 uint32_t mask_size = 0;
1150 struct diag_log_mask_t *log_item = NULL;
1151 struct diag_log_config_req_t *req;
1152 struct diag_log_config_rsp_t rsp;
1153 struct diag_mask_info *mask_info = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301154 struct diag_md_session_t *info = NULL;
1155
1156 mutex_lock(&driver->md_session_lock);
1157 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001158
1159 mask_info = (!info) ? &log_mask : info->log_mask;
1160 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1161 !mask_info) {
1162 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1163 __func__, src_buf, src_len, dest_buf, dest_len,
1164 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301165 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001166 return -EINVAL;
1167 }
Hardik Arya3d3436a2017-09-11 11:37:33 +05301168 if (!mask_info->ptr) {
1169 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
1170 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301171 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301172 return -EINVAL;
1173 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001174
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301175 if (!diag_apps_responds()) {
1176 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001177 return 0;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301178 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001179
1180 req = (struct diag_log_config_req_t *)src_buf;
1181 read_len += req_header_len;
1182
1183 rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
1184 rsp.padding[0] = 0;
1185 rsp.padding[1] = 0;
1186 rsp.padding[2] = 0;
1187 rsp.sub_cmd = DIAG_CMD_OP_GET_LOG_MASK;
1188 /*
1189 * Don't copy the response header now. Copy at the end after
1190 * calculating the status field value
1191 */
1192 write_len += rsp_header_len;
1193
1194 log_item = (struct diag_log_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +05301195 if (!log_item->ptr) {
1196 pr_err("diag: Invalid input in %s, mask: %pK\n",
1197 __func__, log_item);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301198 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301199 return -EINVAL;
1200 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001201 for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
1202 if (log_item->equip_id != req->equip_id)
1203 continue;
1204 mutex_lock(&log_item->lock);
1205 mask_size = LOG_ITEMS_TO_SIZE(log_item->num_items_tools);
1206 /*
1207 * Make sure we have space to fill the response in the buffer.
1208 * Destination buffer should atleast be able to hold equip_id
1209 * (uint32_t), num_items(uint32_t), mask (mask_size) and the
1210 * response header.
1211 */
1212 if ((mask_size + (2 * sizeof(uint32_t)) + rsp_header_len) >
1213 dest_len) {
1214 pr_err("diag: In %s, invalid length: %d, max rsp_len: %d\n",
1215 __func__, mask_size, dest_len);
1216 status = LOG_STATUS_FAIL;
1217 mutex_unlock(&log_item->lock);
1218 break;
1219 }
1220 *(uint32_t *)(dest_buf + write_len) = log_item->equip_id;
1221 write_len += sizeof(uint32_t);
1222 *(uint32_t *)(dest_buf + write_len) = log_item->num_items_tools;
1223 write_len += sizeof(uint32_t);
1224 if (mask_size > 0) {
1225 memcpy(dest_buf + write_len, log_item->ptr, mask_size);
1226 write_len += mask_size;
1227 }
1228 DIAG_LOG(DIAG_DEBUG_MASKS,
1229 "sending log e %d num_items %d size %d\n",
1230 log_item->equip_id, log_item->num_items_tools,
1231 log_item->range_tools);
1232 mutex_unlock(&log_item->lock);
1233 status = LOG_STATUS_SUCCESS;
1234 break;
1235 }
1236
1237 rsp.status = status;
1238 memcpy(dest_buf, &rsp, rsp_header_len);
1239
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301240 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001241 return write_len;
1242}
1243
1244static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301245 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001246{
1247 int i;
1248 int write_len = 0;
1249 struct diag_log_config_rsp_t rsp;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001250 struct diag_log_mask_t *mask = (struct diag_log_mask_t *)log_mask.ptr;
1251
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301252 if (!mask)
1253 return -EINVAL;
1254
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001255 if (!diag_apps_responds())
1256 return 0;
1257
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301258 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
1259 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
1260 __func__, src_buf, src_len, dest_buf, dest_len);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001261 return -EINVAL;
1262 }
1263
1264 rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
1265 rsp.padding[0] = 0;
1266 rsp.padding[1] = 0;
1267 rsp.padding[2] = 0;
1268 rsp.sub_cmd = DIAG_CMD_OP_GET_LOG_RANGE;
1269 rsp.status = LOG_STATUS_SUCCESS;
1270 memcpy(dest_buf, &rsp, sizeof(rsp));
1271 write_len += sizeof(rsp);
1272
1273 for (i = 0; i < MAX_EQUIP_ID && write_len < dest_len; i++, mask++) {
1274 *(uint32_t *)(dest_buf + write_len) = mask->num_items_tools;
1275 write_len += sizeof(uint32_t);
1276 }
1277
1278 return write_len;
1279}
1280
1281static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
1282 unsigned char *dest_buf, int dest_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301283 int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001284{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301285 int i, peripheral, write_len = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001286 int status = LOG_STATUS_SUCCESS;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301287 int read_len = 0, payload_len = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001288 int req_header_len = sizeof(struct diag_log_config_req_t);
1289 int rsp_header_len = sizeof(struct diag_log_config_set_rsp_t);
1290 uint32_t mask_size = 0;
1291 struct diag_log_config_req_t *req;
1292 struct diag_log_config_set_rsp_t rsp;
1293 struct diag_log_mask_t *mask = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001294 struct diag_mask_info *mask_info = NULL;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301295 unsigned char *temp_buf = NULL;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301296 struct diag_md_session_t *info = NULL;
1297
1298 mutex_lock(&driver->md_session_lock);
1299 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001300
1301 mask_info = (!info) ? &log_mask : info->log_mask;
1302 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1303 !mask_info) {
1304 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1305 __func__, src_buf, src_len, dest_buf, dest_len,
1306 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301307 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001308 return -EINVAL;
1309 }
Hardik Arya3d3436a2017-09-11 11:37:33 +05301310 if (!mask_info->ptr) {
1311 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
1312 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301313 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301314 return -EINVAL;
1315 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001316
1317 req = (struct diag_log_config_req_t *)src_buf;
1318 read_len += req_header_len;
1319 mask = (struct diag_log_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +05301320 if (!mask->ptr) {
1321 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
1322 __func__, mask->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301323 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301324 return -EINVAL;
1325 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001326 if (req->equip_id >= MAX_EQUIP_ID) {
1327 pr_err("diag: In %s, Invalid logging mask request, equip_id: %d\n",
1328 __func__, req->equip_id);
1329 status = LOG_STATUS_INVALID;
1330 }
1331
1332 if (req->num_items == 0) {
1333 pr_err("diag: In %s, Invalid number of items in log mask request, equip_id: %d\n",
1334 __func__, req->equip_id);
1335 status = LOG_STATUS_INVALID;
1336 }
1337
1338 mutex_lock(&mask_info->lock);
1339 for (i = 0; i < MAX_EQUIP_ID && !status; i++, mask++) {
1340 if (mask->equip_id != req->equip_id)
1341 continue;
1342 mutex_lock(&mask->lock);
1343
1344 DIAG_LOG(DIAG_DEBUG_MASKS, "e: %d current: %d %d new: %d %d",
1345 mask->equip_id, mask->num_items_tools,
1346 mask->range_tools, req->num_items,
1347 LOG_ITEMS_TO_SIZE(req->num_items));
1348 /*
1349 * If the size of the log mask cannot fit into our
1350 * buffer, trim till we have space left in the buffer.
1351 * num_items should then reflect the items that we have
1352 * in our buffer.
1353 */
1354 mask->num_items_tools = (req->num_items > MAX_ITEMS_ALLOWED) ?
1355 MAX_ITEMS_ALLOWED : req->num_items;
1356 mask_size = LOG_ITEMS_TO_SIZE(mask->num_items_tools);
1357 memset(mask->ptr, 0, mask->range_tools);
1358 if (mask_size > mask->range_tools) {
1359 DIAG_LOG(DIAG_DEBUG_MASKS,
1360 "log range mismatch, e: %d old: %d new: %d\n",
1361 req->equip_id, mask->range_tools,
1362 LOG_ITEMS_TO_SIZE(mask->num_items_tools));
1363 /* Change in the mask reported by tools */
1364 temp_buf = krealloc(mask->ptr, mask_size, GFP_KERNEL);
1365 if (!temp_buf) {
1366 mask_info->status = DIAG_CTRL_MASK_INVALID;
1367 mutex_unlock(&mask->lock);
1368 break;
1369 }
1370 mask->ptr = temp_buf;
1371 memset(mask->ptr, 0, mask_size);
1372 mask->range_tools = mask_size;
1373 }
1374 req->num_items = mask->num_items_tools;
1375 if (mask_size > 0)
1376 memcpy(mask->ptr, src_buf + read_len, mask_size);
1377 DIAG_LOG(DIAG_DEBUG_MASKS,
1378 "copying log mask, e %d num %d range %d size %d\n",
1379 req->equip_id, mask->num_items_tools,
1380 mask->range_tools, mask_size);
1381 mutex_unlock(&mask->lock);
1382 mask_info->status = DIAG_CTRL_MASK_VALID;
1383 break;
1384 }
1385 mutex_unlock(&mask_info->lock);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301386 mutex_unlock(&driver->md_session_lock);
Hardik Arya430b1e72018-04-09 14:49:40 +05301387 if (diag_check_update(APPS_DATA, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001388 diag_update_userspace_clients(LOG_MASKS_TYPE);
1389
1390 /*
1391 * Apps processor must send the response to this command. Frame the
1392 * response.
1393 */
1394 payload_len = LOG_ITEMS_TO_SIZE(req->num_items);
1395 if ((payload_len + rsp_header_len > dest_len) || (payload_len == 0)) {
1396 pr_err("diag: In %s, invalid length, payload_len: %d, header_len: %d, dest_len: %d\n",
1397 __func__, payload_len, rsp_header_len, dest_len);
1398 status = LOG_STATUS_FAIL;
1399 }
1400 rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
1401 rsp.padding[0] = 0;
1402 rsp.padding[1] = 0;
1403 rsp.padding[2] = 0;
1404 rsp.sub_cmd = DIAG_CMD_OP_SET_LOG_MASK;
1405 rsp.status = status;
1406 rsp.equip_id = req->equip_id;
1407 rsp.num_items = req->num_items;
1408 memcpy(dest_buf, &rsp, rsp_header_len);
1409 write_len += rsp_header_len;
1410 if (status != LOG_STATUS_SUCCESS)
1411 goto end;
1412 memcpy(dest_buf + write_len, src_buf + read_len, payload_len);
1413 write_len += payload_len;
1414
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301415 for (i = 0; i < NUM_MD_SESSIONS; i++) {
1416 if (i == APPS_DATA)
1417 continue;
Hardik Arya430b1e72018-04-09 14:49:40 +05301418 if (!diag_check_update(i, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001419 continue;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301420 if (i > NUM_PERIPHERALS)
1421 peripheral = diag_search_peripheral_by_pd(i);
1422 else
1423 peripheral = i;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301424 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301425 diag_send_log_mask_update(peripheral, req->equip_id);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301426 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001427 }
1428end:
1429 return write_len;
1430}
1431
1432static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301433 unsigned char *dest_buf, int dest_len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001434{
1435 struct diag_mask_info *mask_info = NULL;
1436 struct diag_log_mask_t *mask = NULL;
1437 struct diag_log_config_rsp_t header;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301438 int write_len = 0, i, peripheral;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301439 struct diag_md_session_t *info = NULL;
1440
1441 mutex_lock(&driver->md_session_lock);
1442 info = diag_md_session_get_pid(pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001443
1444 mask_info = (!info) ? &log_mask : info->log_mask;
1445 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1446 !mask_info) {
1447 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1448 __func__, src_buf, src_len, dest_buf, dest_len,
1449 mask_info);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301450 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001451 return -EINVAL;
1452 }
Hardik Arya3d3436a2017-09-11 11:37:33 +05301453 if (!mask_info->ptr) {
1454 pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
1455 __func__, mask_info->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301456 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301457 return -EINVAL;
1458 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001459 mask = (struct diag_log_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +05301460 if (!mask->ptr) {
1461 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
1462 __func__, mask->ptr);
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301463 mutex_unlock(&driver->md_session_lock);
Hardik Arya3d3436a2017-09-11 11:37:33 +05301464 return -EINVAL;
1465 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001466 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1467 mutex_lock(&mask->lock);
1468 memset(mask->ptr, 0, mask->range);
1469 mutex_unlock(&mask->lock);
1470 }
1471 mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05301472 mutex_unlock(&driver->md_session_lock);
Hardik Arya430b1e72018-04-09 14:49:40 +05301473 if (diag_check_update(APPS_DATA, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001474 diag_update_userspace_clients(LOG_MASKS_TYPE);
1475
1476 /*
1477 * Apps processor must send the response to this command. Frame the
1478 * response.
1479 */
1480 header.cmd_code = DIAG_CMD_LOG_CONFIG;
1481 header.padding[0] = 0;
1482 header.padding[1] = 0;
1483 header.padding[2] = 0;
1484 header.sub_cmd = DIAG_CMD_OP_LOG_DISABLE;
1485 header.status = LOG_STATUS_SUCCESS;
1486 memcpy(dest_buf, &header, sizeof(struct diag_log_config_rsp_t));
1487 write_len += sizeof(struct diag_log_config_rsp_t);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301488 for (i = 0; i < NUM_MD_SESSIONS; i++) {
1489 if (i == APPS_DATA)
1490 continue;
Hardik Arya430b1e72018-04-09 14:49:40 +05301491 if (!diag_check_update(i, pid))
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001492 continue;
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301493 if (i > NUM_PERIPHERALS)
1494 peripheral = diag_search_peripheral_by_pd(i);
1495 else
1496 peripheral = i;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301497 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301498 diag_send_log_mask_update(peripheral, ALL_EQUIP_ID);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301499 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001500 }
1501
1502 return write_len;
1503}
1504
1505int diag_create_msg_mask_table_entry(struct diag_msg_mask_t *msg_mask,
1506 struct diag_ssid_range_t *range)
1507{
1508 if (!msg_mask || !range)
1509 return -EIO;
1510 if (range->ssid_last < range->ssid_first)
1511 return -EINVAL;
1512 msg_mask->ssid_first = range->ssid_first;
1513 msg_mask->ssid_last = range->ssid_last;
1514 msg_mask->ssid_last_tools = range->ssid_last;
1515 msg_mask->range = msg_mask->ssid_last - msg_mask->ssid_first + 1;
1516 if (msg_mask->range < MAX_SSID_PER_RANGE)
1517 msg_mask->range = MAX_SSID_PER_RANGE;
1518 msg_mask->range_tools = msg_mask->range;
1519 mutex_init(&msg_mask->lock);
1520 if (msg_mask->range > 0) {
1521 msg_mask->ptr = kcalloc(msg_mask->range, sizeof(uint32_t),
1522 GFP_KERNEL);
1523 if (!msg_mask->ptr)
1524 return -ENOMEM;
1525 kmemleak_not_leak(msg_mask->ptr);
1526 }
1527 return 0;
1528}
1529
1530static int diag_create_msg_mask_table(void)
1531{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301532 int i, err = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001533 struct diag_msg_mask_t *mask = (struct diag_msg_mask_t *)msg_mask.ptr;
1534 struct diag_ssid_range_t range;
1535
1536 mutex_lock(&msg_mask.lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301537 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001538 driver->msg_mask_tbl_count = MSG_MASK_TBL_CNT;
1539 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
1540 range.ssid_first = msg_mask_tbl[i].ssid_first;
1541 range.ssid_last = msg_mask_tbl[i].ssid_last;
1542 err = diag_create_msg_mask_table_entry(mask, &range);
1543 if (err)
1544 break;
1545 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301546 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301547 mutex_unlock(&msg_mask.lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001548 return err;
1549}
1550
1551static int diag_create_build_time_mask(void)
1552{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301553 int i, err = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001554 const uint32_t *tbl = NULL;
1555 uint32_t tbl_size = 0;
1556 struct diag_msg_mask_t *build_mask = NULL;
1557 struct diag_ssid_range_t range;
1558
1559 mutex_lock(&msg_bt_mask.lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301560 mutex_lock(&driver->msg_mask_lock);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301561 driver->bt_msg_mask_tbl_count = MSG_MASK_TBL_CNT;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001562 build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301563 for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001564 range.ssid_first = msg_mask_tbl[i].ssid_first;
1565 range.ssid_last = msg_mask_tbl[i].ssid_last;
1566 err = diag_create_msg_mask_table_entry(build_mask, &range);
1567 if (err)
1568 break;
1569 switch (build_mask->ssid_first) {
1570 case MSG_SSID_0:
1571 tbl = msg_bld_masks_0;
1572 tbl_size = sizeof(msg_bld_masks_0);
1573 break;
1574 case MSG_SSID_1:
1575 tbl = msg_bld_masks_1;
1576 tbl_size = sizeof(msg_bld_masks_1);
1577 break;
1578 case MSG_SSID_2:
1579 tbl = msg_bld_masks_2;
1580 tbl_size = sizeof(msg_bld_masks_2);
1581 break;
1582 case MSG_SSID_3:
1583 tbl = msg_bld_masks_3;
1584 tbl_size = sizeof(msg_bld_masks_3);
1585 break;
1586 case MSG_SSID_4:
1587 tbl = msg_bld_masks_4;
1588 tbl_size = sizeof(msg_bld_masks_4);
1589 break;
1590 case MSG_SSID_5:
1591 tbl = msg_bld_masks_5;
1592 tbl_size = sizeof(msg_bld_masks_5);
1593 break;
1594 case MSG_SSID_6:
1595 tbl = msg_bld_masks_6;
1596 tbl_size = sizeof(msg_bld_masks_6);
1597 break;
1598 case MSG_SSID_7:
1599 tbl = msg_bld_masks_7;
1600 tbl_size = sizeof(msg_bld_masks_7);
1601 break;
1602 case MSG_SSID_8:
1603 tbl = msg_bld_masks_8;
1604 tbl_size = sizeof(msg_bld_masks_8);
1605 break;
1606 case MSG_SSID_9:
1607 tbl = msg_bld_masks_9;
1608 tbl_size = sizeof(msg_bld_masks_9);
1609 break;
1610 case MSG_SSID_10:
1611 tbl = msg_bld_masks_10;
1612 tbl_size = sizeof(msg_bld_masks_10);
1613 break;
1614 case MSG_SSID_11:
1615 tbl = msg_bld_masks_11;
1616 tbl_size = sizeof(msg_bld_masks_11);
1617 break;
1618 case MSG_SSID_12:
1619 tbl = msg_bld_masks_12;
1620 tbl_size = sizeof(msg_bld_masks_12);
1621 break;
1622 case MSG_SSID_13:
1623 tbl = msg_bld_masks_13;
1624 tbl_size = sizeof(msg_bld_masks_13);
1625 break;
1626 case MSG_SSID_14:
1627 tbl = msg_bld_masks_14;
1628 tbl_size = sizeof(msg_bld_masks_14);
1629 break;
1630 case MSG_SSID_15:
1631 tbl = msg_bld_masks_15;
1632 tbl_size = sizeof(msg_bld_masks_15);
1633 break;
1634 case MSG_SSID_16:
1635 tbl = msg_bld_masks_16;
1636 tbl_size = sizeof(msg_bld_masks_16);
1637 break;
1638 case MSG_SSID_17:
1639 tbl = msg_bld_masks_17;
1640 tbl_size = sizeof(msg_bld_masks_17);
1641 break;
1642 case MSG_SSID_18:
1643 tbl = msg_bld_masks_18;
1644 tbl_size = sizeof(msg_bld_masks_18);
1645 break;
1646 case MSG_SSID_19:
1647 tbl = msg_bld_masks_19;
1648 tbl_size = sizeof(msg_bld_masks_19);
1649 break;
1650 case MSG_SSID_20:
1651 tbl = msg_bld_masks_20;
1652 tbl_size = sizeof(msg_bld_masks_20);
1653 break;
1654 case MSG_SSID_21:
1655 tbl = msg_bld_masks_21;
1656 tbl_size = sizeof(msg_bld_masks_21);
1657 break;
1658 case MSG_SSID_22:
1659 tbl = msg_bld_masks_22;
1660 tbl_size = sizeof(msg_bld_masks_22);
1661 break;
1662 }
1663 if (!tbl)
1664 continue;
1665 if (tbl_size > build_mask->range * sizeof(uint32_t)) {
1666 pr_warn("diag: In %s, table %d has more ssid than max, ssid_first: %d, ssid_last: %d\n",
1667 __func__, i, build_mask->ssid_first,
1668 build_mask->ssid_last);
1669 tbl_size = build_mask->range * sizeof(uint32_t);
1670 }
1671 memcpy(build_mask->ptr, tbl, tbl_size);
1672 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301673 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301674 mutex_unlock(&msg_bt_mask.lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001675 return err;
1676}
1677
1678static int diag_create_log_mask_table(void)
1679{
1680 struct diag_log_mask_t *mask = NULL;
1681 uint8_t i;
1682 int err = 0;
1683
1684 mutex_lock(&log_mask.lock);
1685 mask = (struct diag_log_mask_t *)(log_mask.ptr);
1686 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1687 mask->equip_id = i;
1688 mask->num_items = LOG_GET_ITEM_NUM(log_code_last_tbl[i]);
1689 mask->num_items_tools = mask->num_items;
1690 mutex_init(&mask->lock);
1691 if (LOG_ITEMS_TO_SIZE(mask->num_items) > MAX_ITEMS_PER_EQUIP_ID)
1692 mask->range = LOG_ITEMS_TO_SIZE(mask->num_items);
1693 else
1694 mask->range = MAX_ITEMS_PER_EQUIP_ID;
1695 mask->range_tools = mask->range;
1696 mask->ptr = kzalloc(mask->range, GFP_KERNEL);
1697 if (!mask->ptr) {
1698 err = -ENOMEM;
1699 break;
1700 }
1701 kmemleak_not_leak(mask->ptr);
1702 }
1703 mutex_unlock(&log_mask.lock);
1704 return err;
1705}
1706
1707static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len,
1708 int update_buf_len)
1709{
1710 if (!mask_info || mask_len < 0 || update_buf_len < 0)
1711 return -EINVAL;
1712
1713 mask_info->status = DIAG_CTRL_MASK_INVALID;
1714 mask_info->mask_len = mask_len;
1715 mask_info->update_buf_len = update_buf_len;
1716 if (mask_len > 0) {
1717 mask_info->ptr = kzalloc(mask_len, GFP_KERNEL);
1718 if (!mask_info->ptr)
1719 return -ENOMEM;
1720 kmemleak_not_leak(mask_info->ptr);
1721 }
1722 if (update_buf_len > 0) {
1723 mask_info->update_buf = kzalloc(update_buf_len, GFP_KERNEL);
1724 if (!mask_info->update_buf) {
1725 kfree(mask_info->ptr);
1726 return -ENOMEM;
1727 }
1728 kmemleak_not_leak(mask_info->update_buf);
1729 }
1730 mutex_init(&mask_info->lock);
1731 return 0;
1732}
1733
1734static void __diag_mask_exit(struct diag_mask_info *mask_info)
1735{
Hardik Arya3d3436a2017-09-11 11:37:33 +05301736 if (!mask_info || !mask_info->ptr)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001737 return;
1738
1739 mutex_lock(&mask_info->lock);
1740 kfree(mask_info->ptr);
1741 mask_info->ptr = NULL;
1742 kfree(mask_info->update_buf);
1743 mask_info->update_buf = NULL;
1744 mutex_unlock(&mask_info->lock);
1745}
1746
1747int diag_log_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
1748{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301749 int i, err = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001750 struct diag_log_mask_t *src_mask = NULL;
1751 struct diag_log_mask_t *dest_mask = NULL;
1752
1753 if (!src)
1754 return -EINVAL;
1755
1756 err = __diag_mask_init(dest, LOG_MASK_SIZE, APPS_BUF_SIZE);
1757 if (err)
1758 return err;
1759
1760 mutex_lock(&dest->lock);
1761 src_mask = (struct diag_log_mask_t *)(src->ptr);
1762 dest_mask = (struct diag_log_mask_t *)(dest->ptr);
1763
1764 dest->mask_len = src->mask_len;
1765 dest->status = src->status;
1766
1767 for (i = 0; i < MAX_EQUIP_ID; i++, src_mask++, dest_mask++) {
1768 dest_mask->equip_id = src_mask->equip_id;
1769 dest_mask->num_items = src_mask->num_items;
1770 dest_mask->num_items_tools = src_mask->num_items_tools;
1771 mutex_init(&dest_mask->lock);
1772 dest_mask->range = src_mask->range;
1773 dest_mask->range_tools = src_mask->range_tools;
1774 dest_mask->ptr = kzalloc(dest_mask->range_tools, GFP_KERNEL);
1775 if (!dest_mask->ptr) {
1776 err = -ENOMEM;
1777 break;
1778 }
1779 kmemleak_not_leak(dest_mask->ptr);
1780 memcpy(dest_mask->ptr, src_mask->ptr, dest_mask->range_tools);
1781 }
1782 mutex_unlock(&dest->lock);
1783
1784 return err;
1785}
1786
1787void diag_log_mask_free(struct diag_mask_info *mask_info)
1788{
1789 int i;
1790 struct diag_log_mask_t *mask = NULL;
1791
Hardik Arya3d3436a2017-09-11 11:37:33 +05301792 if (!mask_info || !mask_info->ptr)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001793 return;
1794
1795 mutex_lock(&mask_info->lock);
1796 mask = (struct diag_log_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +05301797 if (!mask->ptr) {
1798 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
1799 __func__, mask->ptr);
1800 mutex_unlock(&mask_info->lock);
1801 return;
1802 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001803 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1804 kfree(mask->ptr);
1805 mask->ptr = NULL;
1806 }
1807 mutex_unlock(&mask_info->lock);
1808
1809 __diag_mask_exit(mask_info);
1810
1811}
1812
1813static int diag_msg_mask_init(void)
1814{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301815 int err = 0, i;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001816
1817 err = __diag_mask_init(&msg_mask, MSG_MASK_SIZE, APPS_BUF_SIZE);
1818 if (err)
1819 return err;
1820 err = diag_create_msg_mask_table();
1821 if (err) {
1822 pr_err("diag: Unable to create msg masks, err: %d\n", err);
1823 return err;
1824 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301825 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001826 driver->msg_mask = &msg_mask;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001827 for (i = 0; i < NUM_PERIPHERALS; i++)
1828 driver->max_ssid_count[i] = 0;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301829 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001830
1831 return 0;
1832}
1833
1834int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
1835{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301836 int i, err = 0, mask_size = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001837 struct diag_msg_mask_t *src_mask = NULL;
1838 struct diag_msg_mask_t *dest_mask = NULL;
1839 struct diag_ssid_range_t range;
1840
1841 if (!src || !dest)
1842 return -EINVAL;
1843
1844 err = __diag_mask_init(dest, MSG_MASK_SIZE, APPS_BUF_SIZE);
1845 if (err)
1846 return err;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001847 mutex_lock(&dest->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301848 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001849 src_mask = (struct diag_msg_mask_t *)src->ptr;
1850 dest_mask = (struct diag_msg_mask_t *)dest->ptr;
1851
1852 dest->mask_len = src->mask_len;
1853 dest->status = src->status;
1854 for (i = 0; i < driver->msg_mask_tbl_count; i++) {
1855 range.ssid_first = src_mask->ssid_first;
1856 range.ssid_last = src_mask->ssid_last;
1857 err = diag_create_msg_mask_table_entry(dest_mask, &range);
1858 if (err)
1859 break;
Sreelakshmi Gownipalli44164912017-10-17 13:30:10 -07001860 if (src_mask->range_tools < dest_mask->range)
1861 mask_size = src_mask->range_tools * sizeof(uint32_t);
1862 else
1863 mask_size = dest_mask->range * sizeof(uint32_t);
1864 memcpy(dest_mask->ptr, src_mask->ptr, mask_size);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001865 src_mask++;
1866 dest_mask++;
1867 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301868 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301869 mutex_unlock(&dest->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001870 return err;
1871}
1872
1873void diag_msg_mask_free(struct diag_mask_info *mask_info)
1874{
1875 int i;
1876 struct diag_msg_mask_t *mask = NULL;
1877
Hardik Arya3d3436a2017-09-11 11:37:33 +05301878 if (!mask_info || !mask_info->ptr)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001879 return;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001880 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301881 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001882 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Hardik Arya3d3436a2017-09-11 11:37:33 +05301883 if (!mask->ptr) {
1884 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
1885 __func__, mask->ptr);
1886 mutex_unlock(&driver->msg_mask_lock);
1887 mutex_unlock(&mask_info->lock);
1888 return;
1889 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001890 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
1891 kfree(mask->ptr);
1892 mask->ptr = NULL;
1893 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301894 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301895 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001896 __diag_mask_exit(mask_info);
1897}
1898
1899static void diag_msg_mask_exit(void)
1900{
1901 int i;
1902 struct diag_msg_mask_t *mask = NULL;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301903 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001904 mask = (struct diag_msg_mask_t *)(msg_mask.ptr);
1905 if (mask) {
1906 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++)
1907 kfree(mask->ptr);
1908 kfree(msg_mask.ptr);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301909 msg_mask.ptr = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001910 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001911 kfree(msg_mask.update_buf);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301912 msg_mask.update_buf = NULL;
1913 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001914}
1915
1916static int diag_build_time_mask_init(void)
1917{
1918 int err = 0;
1919
1920 /* There is no need for update buffer for Build Time masks */
1921 err = __diag_mask_init(&msg_bt_mask, MSG_MASK_SIZE, 0);
1922 if (err)
1923 return err;
1924 err = diag_create_build_time_mask();
1925 if (err) {
1926 pr_err("diag: Unable to create msg build time masks, err: %d\n",
1927 err);
1928 return err;
1929 }
1930 driver->build_time_mask = &msg_bt_mask;
1931 return 0;
1932}
1933
1934static void diag_build_time_mask_exit(void)
1935{
1936 int i;
1937 struct diag_msg_mask_t *mask = NULL;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301938 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001939 mask = (struct diag_msg_mask_t *)(msg_bt_mask.ptr);
1940 if (mask) {
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301941 for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, mask++)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001942 kfree(mask->ptr);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301943 kfree(msg_bt_mask.ptr);
1944 msg_bt_mask.ptr = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001945 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301946 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001947}
1948
1949static int diag_log_mask_init(void)
1950{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301951 int err = 0, i;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001952
1953 err = __diag_mask_init(&log_mask, LOG_MASK_SIZE, APPS_BUF_SIZE);
1954 if (err)
1955 return err;
1956 err = diag_create_log_mask_table();
1957 if (err)
1958 return err;
1959 driver->log_mask = &log_mask;
1960
1961 for (i = 0; i < NUM_PERIPHERALS; i++)
1962 driver->num_equip_id[i] = 0;
1963
1964 return 0;
1965}
1966
1967static void diag_log_mask_exit(void)
1968{
1969 int i;
1970 struct diag_log_mask_t *mask = NULL;
1971
1972 mask = (struct diag_log_mask_t *)(log_mask.ptr);
1973 if (mask) {
1974 for (i = 0; i < MAX_EQUIP_ID; i++, mask++)
1975 kfree(mask->ptr);
1976 kfree(log_mask.ptr);
1977 }
1978
1979 kfree(log_mask.update_buf);
1980}
1981
1982static int diag_event_mask_init(void)
1983{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05301984 int err = 0, i;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001985
1986 err = __diag_mask_init(&event_mask, EVENT_MASK_SIZE, APPS_BUF_SIZE);
1987 if (err)
1988 return err;
1989 driver->event_mask_size = EVENT_MASK_SIZE;
1990 driver->last_event_id = APPS_EVENT_LAST_ID;
1991 driver->event_mask = &event_mask;
1992
1993 for (i = 0; i < NUM_PERIPHERALS; i++)
1994 driver->num_event_id[i] = 0;
1995
1996 return 0;
1997}
1998
1999int diag_event_mask_copy(struct diag_mask_info *dest,
2000 struct diag_mask_info *src)
2001{
2002 int err = 0;
2003
2004 if (!src || !dest)
2005 return -EINVAL;
2006
2007 err = __diag_mask_init(dest, EVENT_MASK_SIZE, APPS_BUF_SIZE);
2008 if (err)
2009 return err;
2010
2011 mutex_lock(&dest->lock);
2012 dest->mask_len = src->mask_len;
2013 dest->status = src->status;
2014 memcpy(dest->ptr, src->ptr, dest->mask_len);
2015 mutex_unlock(&dest->lock);
2016
2017 return err;
2018}
2019
2020void diag_event_mask_free(struct diag_mask_info *mask_info)
2021{
2022 if (!mask_info)
2023 return;
2024
2025 __diag_mask_exit(mask_info);
2026}
2027
2028static void diag_event_mask_exit(void)
2029{
2030 kfree(event_mask.ptr);
2031 kfree(event_mask.update_buf);
2032}
2033
2034int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
2035 struct diag_md_session_t *info)
2036{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05302037 int i, err = 0, len = 0;
2038 int copy_len = 0, total_len = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002039 struct diag_msg_mask_userspace_t header;
2040 struct diag_mask_info *mask_info = NULL;
2041 struct diag_msg_mask_t *mask = NULL;
2042 unsigned char *ptr = NULL;
2043
2044 if (!buf || count == 0)
2045 return -EINVAL;
2046
2047 mask_info = (!info) ? &msg_mask : info->msg_mask;
2048 if (!mask_info)
2049 return -EIO;
2050
Hardik Arya3d3436a2017-09-11 11:37:33 +05302051 if (!mask_info->ptr || !mask_info->update_buf) {
2052 pr_err("diag: In %s, invalid input mask_info->ptr: %pK, mask_info->update_buf: %pK\n",
2053 __func__, mask_info->ptr, mask_info->update_buf);
2054 return -EINVAL;
2055 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002056 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05302057 mutex_lock(&driver->msg_mask_lock);
2058
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002059 mask = (struct diag_msg_mask_t *)(mask_info->ptr);
Hardik Arya3d3436a2017-09-11 11:37:33 +05302060 if (!mask->ptr) {
2061 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
2062 __func__, mask->ptr);
2063 mutex_unlock(&driver->msg_mask_lock);
2064 mutex_unlock(&mask_info->lock);
2065 return -EINVAL;
2066 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002067 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
2068 ptr = mask_info->update_buf;
2069 len = 0;
2070 mutex_lock(&mask->lock);
2071 header.ssid_first = mask->ssid_first;
2072 header.ssid_last = mask->ssid_last_tools;
2073 header.range = mask->range_tools;
2074 memcpy(ptr, &header, sizeof(header));
2075 len += sizeof(header);
2076 copy_len = (sizeof(uint32_t) * mask->range_tools);
2077 if ((len + copy_len) > mask_info->update_buf_len) {
2078 pr_err("diag: In %s, no space to update msg mask, first: %d, last: %d\n",
2079 __func__, mask->ssid_first,
2080 mask->ssid_last_tools);
2081 mutex_unlock(&mask->lock);
2082 continue;
2083 }
2084 memcpy(ptr + len, mask->ptr, copy_len);
2085 len += copy_len;
2086 mutex_unlock(&mask->lock);
2087 /* + sizeof(int) to account for data_type already in buf */
2088 if (total_len + sizeof(int) + len > count) {
2089 pr_err("diag: In %s, unable to send msg masks to user space, total_len: %d, count: %zu\n",
2090 __func__, total_len, count);
2091 err = -ENOMEM;
2092 break;
2093 }
2094 err = copy_to_user(buf + total_len, (void *)ptr, len);
2095 if (err) {
2096 pr_err("diag: In %s Unable to send msg masks to user space clients, err: %d\n",
2097 __func__, err);
2098 break;
2099 }
2100 total_len += len;
2101 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05302102 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05302103 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002104 return err ? err : total_len;
2105}
2106
2107int diag_copy_to_user_log_mask(char __user *buf, size_t count,
2108 struct diag_md_session_t *info)
2109{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05302110 int i, err = 0, len = 0;
2111 int copy_len = 0, total_len = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002112 struct diag_log_mask_userspace_t header;
2113 struct diag_log_mask_t *mask = NULL;
2114 struct diag_mask_info *mask_info = NULL;
2115 unsigned char *ptr = NULL;
2116
2117 if (!buf || count == 0)
2118 return -EINVAL;
2119
2120 mask_info = (!info) ? &log_mask : info->log_mask;
2121 if (!mask_info)
2122 return -EIO;
2123
Hardik Arya3d3436a2017-09-11 11:37:33 +05302124 if (!mask_info->ptr || !mask_info->update_buf) {
2125 pr_err("diag: In %s, invalid input mask_info->ptr: %pK, mask_info->update_buf: %pK\n",
2126 __func__, mask_info->ptr, mask_info->update_buf);
2127 return -EINVAL;
2128 }
2129
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002130 mutex_lock(&mask_info->lock);
2131 mask = (struct diag_log_mask_t *)(mask_info->ptr);
Hardik Arya3d3436a2017-09-11 11:37:33 +05302132 if (!mask->ptr) {
2133 pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
2134 __func__, mask->ptr);
2135 mutex_unlock(&mask_info->lock);
2136 return -EINVAL;
2137 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002138 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
2139 ptr = mask_info->update_buf;
2140 len = 0;
2141 mutex_lock(&mask->lock);
2142 header.equip_id = mask->equip_id;
2143 header.num_items = mask->num_items_tools;
2144 memcpy(ptr, &header, sizeof(header));
2145 len += sizeof(header);
2146 copy_len = LOG_ITEMS_TO_SIZE(header.num_items);
2147 if ((len + copy_len) > mask_info->update_buf_len) {
2148 pr_err("diag: In %s, no space to update log mask, equip_id: %d\n",
2149 __func__, mask->equip_id);
2150 mutex_unlock(&mask->lock);
2151 continue;
2152 }
2153 memcpy(ptr + len, mask->ptr, copy_len);
2154 len += copy_len;
2155 mutex_unlock(&mask->lock);
2156 /* + sizeof(int) to account for data_type already in buf */
2157 if (total_len + sizeof(int) + len > count) {
2158 pr_err("diag: In %s, unable to send log masks to user space, total_len: %d, count: %zu\n",
2159 __func__, total_len, count);
2160 err = -ENOMEM;
2161 break;
2162 }
2163 err = copy_to_user(buf + total_len, (void *)ptr, len);
2164 if (err) {
2165 pr_err("diag: In %s Unable to send log masks to user space clients, err: %d\n",
2166 __func__, err);
2167 break;
2168 }
2169 total_len += len;
2170 }
2171 mutex_unlock(&mask_info->lock);
2172
2173 return err ? err : total_len;
2174}
2175
2176void diag_send_updates_peripheral(uint8_t peripheral)
2177{
Manoj Prabhu B9553b462017-09-25 09:59:47 +05302178 if (!driver->feature[peripheral].sent_feature_mask)
2179 diag_send_feature_mask_update(peripheral);
Manoj Prabhu B571cf422017-08-08 19:01:41 +05302180 /*
2181 * Masks (F3, logs and events) will be sent to
2182 * peripheral immediately following feature mask update only
2183 * if diag_id support is not present or
2184 * diag_id support is present and diag_id has been sent to
2185 * peripheral.
2186 */
2187 if (!driver->feature[peripheral].diag_id_support ||
2188 driver->diag_id_sent[peripheral]) {
2189 if (driver->time_sync_enabled)
2190 diag_send_time_sync_update(peripheral);
2191 mutex_lock(&driver->md_session_lock);
Manoj Prabhu B5e429862018-02-28 15:21:42 +05302192 if (driver->set_mask_cmd) {
2193 diag_send_msg_mask_update(peripheral,
2194 ALL_SSID, ALL_SSID);
2195 diag_send_log_mask_update(peripheral, ALL_EQUIP_ID);
2196 diag_send_event_mask_update(peripheral);
2197 }
Manoj Prabhu B571cf422017-08-08 19:01:41 +05302198 mutex_unlock(&driver->md_session_lock);
2199 diag_send_real_time_update(peripheral,
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002200 driver->real_time_mode[DIAG_LOCAL_PROC]);
Manoj Prabhu B571cf422017-08-08 19:01:41 +05302201 diag_send_peripheral_buffering_mode(
2202 &driver->buffering_mode[peripheral]);
Manoj Prabhu B9ac639f2017-11-21 21:37:11 +05302203
2204 /*
2205 * Clear mask_update variable afer updating
2206 * logging masks to peripheral.
2207 */
2208 mutex_lock(&driver->cntl_lock);
2209 driver->mask_update ^= PERIPHERAL_MASK(peripheral);
2210 mutex_unlock(&driver->cntl_lock);
Manoj Prabhu B571cf422017-08-08 19:01:41 +05302211 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002212}
2213
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05302214int diag_process_apps_masks(unsigned char *buf, int len, int pid)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002215{
Manoj Prabhu B90e1f502017-11-02 20:01:45 +05302216 int size = 0, sub_cmd = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002217 int (*hdlr)(unsigned char *src_buf, int src_len,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05302218 unsigned char *dest_buf, int dest_len, int pid) = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002219
2220 if (!buf || len <= 0)
2221 return -EINVAL;
2222
2223 if (*buf == DIAG_CMD_LOG_CONFIG) {
2224 sub_cmd = *(int *)(buf + sizeof(int));
2225 switch (sub_cmd) {
2226 case DIAG_CMD_OP_LOG_DISABLE:
2227 hdlr = diag_cmd_disable_log_mask;
2228 break;
2229 case DIAG_CMD_OP_GET_LOG_RANGE:
2230 hdlr = diag_cmd_get_log_range;
2231 break;
2232 case DIAG_CMD_OP_SET_LOG_MASK:
2233 hdlr = diag_cmd_set_log_mask;
Manoj Prabhu B5e429862018-02-28 15:21:42 +05302234 driver->set_mask_cmd = 1;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002235 break;
2236 case DIAG_CMD_OP_GET_LOG_MASK:
2237 hdlr = diag_cmd_get_log_mask;
2238 break;
2239 }
2240 } else if (*buf == DIAG_CMD_MSG_CONFIG) {
2241 sub_cmd = *(uint8_t *)(buf + sizeof(uint8_t));
2242 switch (sub_cmd) {
2243 case DIAG_CMD_OP_GET_SSID_RANGE:
2244 hdlr = diag_cmd_get_ssid_range;
2245 break;
2246 case DIAG_CMD_OP_GET_BUILD_MASK:
2247 hdlr = diag_cmd_get_build_mask;
2248 break;
2249 case DIAG_CMD_OP_GET_MSG_MASK:
2250 hdlr = diag_cmd_get_msg_mask;
2251 break;
2252 case DIAG_CMD_OP_SET_MSG_MASK:
2253 hdlr = diag_cmd_set_msg_mask;
Manoj Prabhu B5e429862018-02-28 15:21:42 +05302254 driver->set_mask_cmd = 1;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002255 break;
2256 case DIAG_CMD_OP_SET_ALL_MSG_MASK:
2257 hdlr = diag_cmd_set_all_msg_mask;
Manoj Prabhu B5e429862018-02-28 15:21:42 +05302258 driver->set_mask_cmd = 1;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002259 break;
2260 }
2261 } else if (*buf == DIAG_CMD_GET_EVENT_MASK) {
2262 hdlr = diag_cmd_get_event_mask;
2263 } else if (*buf == DIAG_CMD_SET_EVENT_MASK) {
2264 hdlr = diag_cmd_update_event_mask;
Manoj Prabhu B5e429862018-02-28 15:21:42 +05302265 driver->set_mask_cmd = 1;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002266 } else if (*buf == DIAG_CMD_EVENT_TOGGLE) {
2267 hdlr = diag_cmd_toggle_events;
Manoj Prabhu B5e429862018-02-28 15:21:42 +05302268 driver->set_mask_cmd = 1;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002269 }
2270
2271 if (hdlr)
2272 size = hdlr(buf, len, driver->apps_rsp_buf,
Hardik Aryadbb1c2a2017-11-10 16:29:16 +05302273 DIAG_MAX_RSP_SIZE, pid);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002274
2275 return (size > 0) ? size : 0;
2276}
2277
2278int diag_masks_init(void)
2279{
2280 int err = 0;
2281
2282 err = diag_msg_mask_init();
2283 if (err)
2284 goto fail;
2285
2286 err = diag_build_time_mask_init();
2287 if (err)
2288 goto fail;
2289
2290 err = diag_log_mask_init();
2291 if (err)
2292 goto fail;
2293
2294 err = diag_event_mask_init();
2295 if (err)
2296 goto fail;
2297
2298 if (driver->buf_feature_mask_update == NULL) {
2299 driver->buf_feature_mask_update = kzalloc(sizeof(
2300 struct diag_ctrl_feature_mask) +
2301 FEATURE_MASK_LEN, GFP_KERNEL);
2302 if (driver->buf_feature_mask_update == NULL)
2303 goto fail;
2304 kmemleak_not_leak(driver->buf_feature_mask_update);
2305 }
2306
2307 return 0;
2308fail:
2309 pr_err("diag: Could not initialize diag mask buffers\n");
2310 diag_masks_exit();
2311 return -ENOMEM;
2312}
2313
2314void diag_masks_exit(void)
2315{
2316 diag_msg_mask_exit();
2317 diag_build_time_mask_exit();
2318 diag_log_mask_exit();
2319 diag_event_mask_exit();
2320 kfree(driver->buf_feature_mask_update);
2321}