blob: d734e298c44c079b3abbe0bcee74a4aa5e4e3e43 [file] [log] [blame]
Sreelakshmi Gownipalli8d477d32017-02-08 19:49:06 -08001/* Copyright (c) 2008-2017, 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
30#define diag_check_update(x) \
Manoj Prabhu B571cf422017-08-08 19:01:41 +053031 (!info || (info && (info->peripheral_mask & MD_PERIPHERAL_MASK(x))) \
32 || (info && (info->peripheral_mask & MD_PERIPHERAL_PD_MASK(x)))) \
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070033
34struct diag_mask_info msg_mask;
35struct diag_mask_info msg_bt_mask;
36struct diag_mask_info log_mask;
37struct diag_mask_info event_mask;
38
39static const struct diag_ssid_range_t msg_mask_tbl[] = {
40 { .ssid_first = MSG_SSID_0, .ssid_last = MSG_SSID_0_LAST },
41 { .ssid_first = MSG_SSID_1, .ssid_last = MSG_SSID_1_LAST },
42 { .ssid_first = MSG_SSID_2, .ssid_last = MSG_SSID_2_LAST },
43 { .ssid_first = MSG_SSID_3, .ssid_last = MSG_SSID_3_LAST },
44 { .ssid_first = MSG_SSID_4, .ssid_last = MSG_SSID_4_LAST },
45 { .ssid_first = MSG_SSID_5, .ssid_last = MSG_SSID_5_LAST },
46 { .ssid_first = MSG_SSID_6, .ssid_last = MSG_SSID_6_LAST },
47 { .ssid_first = MSG_SSID_7, .ssid_last = MSG_SSID_7_LAST },
48 { .ssid_first = MSG_SSID_8, .ssid_last = MSG_SSID_8_LAST },
49 { .ssid_first = MSG_SSID_9, .ssid_last = MSG_SSID_9_LAST },
50 { .ssid_first = MSG_SSID_10, .ssid_last = MSG_SSID_10_LAST },
51 { .ssid_first = MSG_SSID_11, .ssid_last = MSG_SSID_11_LAST },
52 { .ssid_first = MSG_SSID_12, .ssid_last = MSG_SSID_12_LAST },
53 { .ssid_first = MSG_SSID_13, .ssid_last = MSG_SSID_13_LAST },
54 { .ssid_first = MSG_SSID_14, .ssid_last = MSG_SSID_14_LAST },
55 { .ssid_first = MSG_SSID_15, .ssid_last = MSG_SSID_15_LAST },
56 { .ssid_first = MSG_SSID_16, .ssid_last = MSG_SSID_16_LAST },
57 { .ssid_first = MSG_SSID_17, .ssid_last = MSG_SSID_17_LAST },
58 { .ssid_first = MSG_SSID_18, .ssid_last = MSG_SSID_18_LAST },
59 { .ssid_first = MSG_SSID_19, .ssid_last = MSG_SSID_19_LAST },
60 { .ssid_first = MSG_SSID_20, .ssid_last = MSG_SSID_20_LAST },
61 { .ssid_first = MSG_SSID_21, .ssid_last = MSG_SSID_21_LAST },
62 { .ssid_first = MSG_SSID_22, .ssid_last = MSG_SSID_22_LAST },
63 { .ssid_first = MSG_SSID_23, .ssid_last = MSG_SSID_23_LAST },
Chris Lewd7316402017-06-19 15:42:50 -070064 { .ssid_first = MSG_SSID_24, .ssid_last = MSG_SSID_24_LAST },
65 { .ssid_first = MSG_SSID_25, .ssid_last = MSG_SSID_25_LAST }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070066};
67
68static int diag_apps_responds(void)
69{
70 /*
71 * Apps processor should respond to mask commands only if the
72 * Modem channel is up, the feature mask is received from Modem
73 * and if Modem supports Mask Centralization.
74 */
75 if (!chk_apps_only())
76 return 0;
77
78 if (driver->diagfwd_cntl[PERIPHERAL_MODEM] &&
79 driver->diagfwd_cntl[PERIPHERAL_MODEM]->ch_open &&
80 driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask) {
81 if (driver->feature[PERIPHERAL_MODEM].mask_centralization)
82 return 1;
83 return 0;
84 }
85 return 1;
86}
87
88static void diag_send_log_mask_update(uint8_t peripheral, int equip_id)
89{
90 int i;
91 int err = 0;
92 int send_once = 0;
93 int header_len = sizeof(struct diag_ctrl_log_mask);
Manoj Prabhu B571cf422017-08-08 19:01:41 +053094 uint8_t *buf = NULL, *temp = NULL;
95 uint8_t upd = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -070096 uint32_t mask_size = 0;
97 struct diag_ctrl_log_mask ctrl_pkt;
98 struct diag_mask_info *mask_info = NULL;
99 struct diag_log_mask_t *mask = NULL;
100
101 if (peripheral >= NUM_PERIPHERALS)
102 return;
103
104 if (!driver->diagfwd_cntl[peripheral] ||
105 !driver->diagfwd_cntl[peripheral]->ch_open) {
106 pr_debug("diag: In %s, control channel is not open, p: %d\n",
107 __func__, peripheral);
108 return;
109 }
110
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530111 if (driver->md_session_mask != 0) {
112 if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
113 if (driver->md_session_map[peripheral])
114 mask_info =
115 driver->md_session_map[peripheral]->log_mask;
116 } else if (driver->md_session_mask &
117 MD_PERIPHERAL_PD_MASK(peripheral)) {
118 upd = diag_mask_to_pd_value(driver->md_session_mask);
119 if (upd && driver->md_session_map[upd])
120 mask_info =
121 driver->md_session_map[upd]->log_mask;
122 } else {
123 DIAG_LOG(DIAG_DEBUG_MASKS,
124 "asking for mask update with unknown session mask\n");
125 return;
126 }
127 } else {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700128 mask_info = &log_mask;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530129 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700130
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530131 if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700132 return;
133
134 mask = (struct diag_log_mask_t *)mask_info->ptr;
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530135 if (!mask->ptr)
136 return;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700137 buf = mask_info->update_buf;
138
139 switch (mask_info->status) {
140 case DIAG_CTRL_MASK_ALL_DISABLED:
141 ctrl_pkt.equip_id = 0;
142 ctrl_pkt.num_items = 0;
143 ctrl_pkt.log_mask_size = 0;
144 send_once = 1;
145 break;
146 case DIAG_CTRL_MASK_ALL_ENABLED:
147 ctrl_pkt.equip_id = 0;
148 ctrl_pkt.num_items = 0;
149 ctrl_pkt.log_mask_size = 0;
150 send_once = 1;
151 break;
152 case DIAG_CTRL_MASK_VALID:
153 send_once = 0;
154 break;
155 default:
156 pr_debug("diag: In %s, invalid log_mask status\n", __func__);
157 return;
158 }
159
160 mutex_lock(&mask_info->lock);
161 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
162 if (equip_id != i && equip_id != ALL_EQUIP_ID)
163 continue;
164
165 mutex_lock(&mask->lock);
166 ctrl_pkt.cmd_type = DIAG_CTRL_MSG_LOG_MASK;
167 ctrl_pkt.stream_id = 1;
168 ctrl_pkt.status = mask_info->status;
169 if (mask_info->status == DIAG_CTRL_MASK_VALID) {
170 mask_size = LOG_ITEMS_TO_SIZE(mask->num_items_tools);
171 ctrl_pkt.equip_id = i;
172 ctrl_pkt.num_items = mask->num_items_tools;
173 ctrl_pkt.log_mask_size = mask_size;
174 }
175 ctrl_pkt.data_len = LOG_MASK_CTRL_HEADER_LEN + mask_size;
176
177 if (header_len + mask_size > mask_info->update_buf_len) {
178 temp = krealloc(buf, header_len + mask_size,
179 GFP_KERNEL);
180 if (!temp) {
181 pr_err_ratelimited("diag: Unable to realloc log update buffer, new size: %d, equip_id: %d\n",
182 header_len + mask_size, equip_id);
183 mutex_unlock(&mask->lock);
184 break;
185 }
186 mask_info->update_buf = temp;
187 mask_info->update_buf_len = header_len + mask_size;
188 }
189
190 memcpy(buf, &ctrl_pkt, header_len);
191 if (mask_size > 0)
192 memcpy(buf + header_len, mask->ptr, mask_size);
193 mutex_unlock(&mask->lock);
194
195 DIAG_LOG(DIAG_DEBUG_MASKS,
196 "sending ctrl pkt to %d, e %d num_items %d size %d\n",
197 peripheral, i, ctrl_pkt.num_items,
198 ctrl_pkt.log_mask_size);
199
200 err = diagfwd_write(peripheral, TYPE_CNTL,
201 buf, header_len + mask_size);
202 if (err && err != -ENODEV)
203 pr_err_ratelimited("diag: Unable to send log masks to peripheral %d, equip_id: %d, err: %d\n",
204 peripheral, i, err);
205 if (send_once || equip_id != ALL_EQUIP_ID)
206 break;
207
208 }
209 mutex_unlock(&mask_info->lock);
210}
211
212static void diag_send_event_mask_update(uint8_t peripheral)
213{
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530214 uint8_t *buf = NULL, *temp = NULL;
215 uint8_t upd = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700216 struct diag_ctrl_event_mask header;
217 struct diag_mask_info *mask_info = NULL;
218 int num_bytes = EVENT_COUNT_TO_BYTES(driver->last_event_id);
219 int write_len = 0;
220 int err = 0;
221 int temp_len = 0;
222
223 if (num_bytes <= 0 || num_bytes > driver->event_mask_size) {
224 pr_debug("diag: In %s, invalid event mask length %d\n",
225 __func__, num_bytes);
226 return;
227 }
228
229 if (peripheral >= NUM_PERIPHERALS)
230 return;
231
232 if (!driver->diagfwd_cntl[peripheral] ||
233 !driver->diagfwd_cntl[peripheral]->ch_open) {
234 pr_debug("diag: In %s, control channel is not open, p: %d\n",
235 __func__, peripheral);
236 return;
237 }
238
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530239 if (driver->md_session_mask != 0) {
240 if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
241 if (driver->md_session_map[peripheral])
242 mask_info =
243 driver->md_session_map[peripheral]->event_mask;
244 } else if (driver->md_session_mask &
245 MD_PERIPHERAL_PD_MASK(peripheral)) {
246 upd = diag_mask_to_pd_value(driver->md_session_mask);
247 if (upd && driver->md_session_map[upd])
248 mask_info =
249 driver->md_session_map[upd]->event_mask;
250 } else {
251 DIAG_LOG(DIAG_DEBUG_MASKS,
252 "asking for mask update with unknown session mask\n");
253 return;
254 }
255 } else {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700256 mask_info = &event_mask;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530257 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700258
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530259 if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700260 return;
261
262 buf = mask_info->update_buf;
263 mutex_lock(&mask_info->lock);
264 header.cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
265 header.stream_id = 1;
266 header.status = mask_info->status;
267
268 switch (mask_info->status) {
269 case DIAG_CTRL_MASK_ALL_DISABLED:
270 header.event_config = 0;
271 header.event_mask_size = 0;
272 break;
273 case DIAG_CTRL_MASK_ALL_ENABLED:
274 header.event_config = 1;
275 header.event_mask_size = 0;
276 break;
277 case DIAG_CTRL_MASK_VALID:
278 header.event_config = 1;
279 header.event_mask_size = num_bytes;
280 if (num_bytes + sizeof(header) > mask_info->update_buf_len) {
281 temp_len = num_bytes + sizeof(header);
282 temp = krealloc(buf, temp_len, GFP_KERNEL);
283 if (!temp) {
284 pr_err("diag: Unable to realloc event mask update buffer\n");
285 goto err;
286 } else {
287 mask_info->update_buf = temp;
288 mask_info->update_buf_len = temp_len;
289 }
290 }
291 memcpy(buf + sizeof(header), mask_info->ptr, num_bytes);
292 write_len += num_bytes;
293 break;
294 default:
295 pr_debug("diag: In %s, invalid status %d\n", __func__,
296 mask_info->status);
297 goto err;
298 }
299 header.data_len = EVENT_MASK_CTRL_HEADER_LEN + header.event_mask_size;
300 memcpy(buf, &header, sizeof(header));
301 write_len += sizeof(header);
302
303 err = diagfwd_write(peripheral, TYPE_CNTL, buf, write_len);
304 if (err && err != -ENODEV)
305 pr_err_ratelimited("diag: Unable to send event masks to peripheral %d\n",
306 peripheral);
307err:
308 mutex_unlock(&mask_info->lock);
309}
310
311static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)
312{
313 int i;
314 int err = 0;
315 int header_len = sizeof(struct diag_ctrl_msg_mask);
316 int temp_len = 0;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530317 uint8_t *buf = NULL, *temp = NULL;
318 uint8_t upd = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700319 uint32_t mask_size = 0;
320 struct diag_mask_info *mask_info = NULL;
321 struct diag_msg_mask_t *mask = NULL;
322 struct diag_ctrl_msg_mask header;
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530323 uint8_t msg_mask_tbl_count_local;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700324
325 if (peripheral >= NUM_PERIPHERALS)
326 return;
327
328 if (!driver->diagfwd_cntl[peripheral] ||
329 !driver->diagfwd_cntl[peripheral]->ch_open) {
330 pr_debug("diag: In %s, control channel is not open, p: %d\n",
331 __func__, peripheral);
332 return;
333 }
334
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530335 if (driver->md_session_mask != 0) {
336 if (driver->md_session_mask & MD_PERIPHERAL_MASK(peripheral)) {
337 if (driver->md_session_map[peripheral])
338 mask_info =
339 driver->md_session_map[peripheral]->msg_mask;
340 } else if (driver->md_session_mask &
341 MD_PERIPHERAL_PD_MASK(peripheral)) {
342 upd = diag_mask_to_pd_value(driver->md_session_mask);
343 if (upd && driver->md_session_map[upd])
344 mask_info =
345 driver->md_session_map[upd]->msg_mask;
346 } else {
347 DIAG_LOG(DIAG_DEBUG_MASKS,
348 "asking for mask update with unknown session mask\n");
349 return;
350 }
351 } else {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700352 mask_info = &msg_mask;
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530353 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700354
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530355 if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700356 return;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530357 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700358 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530359 if (!mask->ptr) {
360 mutex_unlock(&driver->msg_mask_lock);
Mohit Aggarwal9d2727a2017-03-06 10:46:20 +0530361 return;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530362 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700363 buf = mask_info->update_buf;
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530364 msg_mask_tbl_count_local = driver->msg_mask_tbl_count;
365 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700366 mutex_lock(&mask_info->lock);
367 switch (mask_info->status) {
368 case DIAG_CTRL_MASK_ALL_DISABLED:
369 mask_size = 0;
370 break;
371 case DIAG_CTRL_MASK_ALL_ENABLED:
372 mask_size = 1;
373 break;
374 case DIAG_CTRL_MASK_VALID:
375 break;
376 default:
377 pr_debug("diag: In %s, invalid status: %d\n", __func__,
378 mask_info->status);
379 goto err;
380 }
381
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530382 for (i = 0; i < msg_mask_tbl_count_local; i++, mask++) {
383 mutex_lock(&driver->msg_mask_lock);
384 if (((mask->ssid_first > first) ||
385 (mask->ssid_last_tools < last)) && first != ALL_SSID) {
386 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700387 continue;
388 }
389
390 mutex_lock(&mask->lock);
391 if (mask_info->status == DIAG_CTRL_MASK_VALID) {
392 mask_size =
393 mask->ssid_last_tools - mask->ssid_first + 1;
394 temp_len = mask_size * sizeof(uint32_t);
395 if (temp_len + header_len <= mask_info->update_buf_len)
396 goto proceed;
397 temp = krealloc(mask_info->update_buf, temp_len,
398 GFP_KERNEL);
399 if (!temp) {
400 pr_err("diag: In %s, unable to realloc msg_mask update buffer\n",
401 __func__);
402 mask_size = (mask_info->update_buf_len -
403 header_len) / sizeof(uint32_t);
404 } else {
405 mask_info->update_buf = temp;
406 mask_info->update_buf_len = temp_len;
407 pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n",
408 __func__, mask_info->update_buf_len);
409 }
410 } else if (mask_info->status == DIAG_CTRL_MASK_ALL_ENABLED) {
411 mask_size = 1;
412 }
413proceed:
414 header.cmd_type = DIAG_CTRL_MSG_F3_MASK;
415 header.status = mask_info->status;
416 header.stream_id = 1;
417 header.msg_mode = 0;
418 header.ssid_first = mask->ssid_first;
419 header.ssid_last = mask->ssid_last_tools;
420 header.msg_mask_size = mask_size;
421 mask_size *= sizeof(uint32_t);
422 header.data_len = MSG_MASK_CTRL_HEADER_LEN + mask_size;
423 memcpy(buf, &header, header_len);
424 if (mask_size > 0)
425 memcpy(buf + header_len, mask->ptr, mask_size);
426 mutex_unlock(&mask->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530427 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700428
429 err = diagfwd_write(peripheral, TYPE_CNTL, buf,
430 header_len + mask_size);
431 if (err && err != -ENODEV)
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530432 pr_err_ratelimited("diag: Unable to send msg masks to peripheral %d, error = %d\n",
433 peripheral, err);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700434
435 if (first != ALL_SSID)
436 break;
437 }
438err:
439 mutex_unlock(&mask_info->lock);
440}
441
442static void diag_send_time_sync_update(uint8_t peripheral)
443{
444 struct diag_ctrl_msg_time_sync time_sync_msg;
445 int msg_size = sizeof(struct diag_ctrl_msg_time_sync);
446 int err = 0;
447
448 if (peripheral >= NUM_PERIPHERALS) {
449 pr_err("diag: In %s, Invalid peripheral, %d\n",
450 __func__, peripheral);
451 return;
452 }
453
454 if (!driver->diagfwd_cntl[peripheral] ||
455 !driver->diagfwd_cntl[peripheral]->ch_open) {
456 pr_err("diag: In %s, control channel is not open, p: %d, %pK\n",
457 __func__, peripheral, driver->diagfwd_cntl[peripheral]);
458 return;
459 }
460
461 mutex_lock(&driver->diag_cntl_mutex);
462 time_sync_msg.ctrl_pkt_id = DIAG_CTRL_MSG_TIME_SYNC_PKT;
463 time_sync_msg.ctrl_pkt_data_len = 5;
464 time_sync_msg.version = 1;
465 time_sync_msg.time_api = driver->uses_time_api;
466
467 err = diagfwd_write(peripheral, TYPE_CNTL, &time_sync_msg, msg_size);
468 if (err)
469 pr_err("diag: In %s, unable to write to peripheral: %d, type: %d, len: %d, err: %d\n",
470 __func__, peripheral, TYPE_CNTL,
471 msg_size, err);
472 mutex_unlock(&driver->diag_cntl_mutex);
473}
474
475static void diag_send_feature_mask_update(uint8_t peripheral)
476{
477 void *buf = driver->buf_feature_mask_update;
478 int header_size = sizeof(struct diag_ctrl_feature_mask);
479 uint8_t feature_bytes[FEATURE_MASK_LEN] = {0, 0};
480 struct diag_ctrl_feature_mask feature_mask;
481 int total_len = 0;
482 int err = 0;
483
484 if (peripheral >= NUM_PERIPHERALS) {
485 pr_err("diag: In %s, Invalid peripheral, %d\n",
486 __func__, peripheral);
487 return;
488 }
489
490 if (!driver->diagfwd_cntl[peripheral] ||
491 !driver->diagfwd_cntl[peripheral]->ch_open) {
492 pr_err("diag: In %s, control channel is not open, p: %d, %pK\n",
493 __func__, peripheral, driver->diagfwd_cntl[peripheral]);
494 return;
495 }
496
497 mutex_lock(&driver->diag_cntl_mutex);
498 /* send feature mask update */
499 feature_mask.ctrl_pkt_id = DIAG_CTRL_MSG_FEATURE;
500 feature_mask.ctrl_pkt_data_len = sizeof(uint32_t) + FEATURE_MASK_LEN;
501 feature_mask.feature_mask_len = FEATURE_MASK_LEN;
502 memcpy(buf, &feature_mask, header_size);
503 DIAG_SET_FEATURE_MASK(F_DIAG_FEATURE_MASK_SUPPORT);
504 DIAG_SET_FEATURE_MASK(F_DIAG_LOG_ON_DEMAND_APPS);
505 DIAG_SET_FEATURE_MASK(F_DIAG_STM);
506 DIAG_SET_FEATURE_MASK(F_DIAG_DCI_EXTENDED_HEADER_SUPPORT);
Sreelakshmi Gownipalli8d477d32017-02-08 19:49:06 -0800507 DIAG_SET_FEATURE_MASK(F_DIAG_DIAGID_SUPPORT);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700508 if (driver->supports_separate_cmdrsp)
509 DIAG_SET_FEATURE_MASK(F_DIAG_REQ_RSP_SUPPORT);
510 if (driver->supports_apps_hdlc_encoding)
511 DIAG_SET_FEATURE_MASK(F_DIAG_APPS_HDLC_ENCODE);
Manoj Prabhu B571cf422017-08-08 19:01:41 +0530512 if (driver->supports_apps_header_untagging) {
513 if (peripheral == PERIPHERAL_MODEM) {
514 DIAG_SET_FEATURE_MASK(F_DIAG_PKT_HEADER_UNTAG);
515 driver->peripheral_untag[peripheral] =
516 ENABLE_PKT_HEADER_UNTAGGING;
517 }
518 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700519 DIAG_SET_FEATURE_MASK(F_DIAG_MASK_CENTRALIZATION);
520 if (driver->supports_sockets)
521 DIAG_SET_FEATURE_MASK(F_DIAG_SOCKETS_ENABLED);
522
523 memcpy(buf + header_size, &feature_bytes, FEATURE_MASK_LEN);
524 total_len = header_size + FEATURE_MASK_LEN;
525
526 err = diagfwd_write(peripheral, TYPE_CNTL, buf, total_len);
527 if (err) {
528 pr_err_ratelimited("diag: In %s, unable to write feature mask to peripheral: %d, type: %d, len: %d, err: %d\n",
529 __func__, peripheral, TYPE_CNTL,
530 total_len, err);
531 mutex_unlock(&driver->diag_cntl_mutex);
532 return;
533 }
534 driver->feature[peripheral].sent_feature_mask = 1;
535 mutex_unlock(&driver->diag_cntl_mutex);
536}
537
538static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
539 unsigned char *dest_buf, int dest_len,
540 struct diag_md_session_t *info)
541{
542 int i;
543 int write_len = 0;
544 struct diag_msg_mask_t *mask_ptr = NULL;
545 struct diag_msg_ssid_query_t rsp;
546 struct diag_ssid_range_t ssid_range;
547 struct diag_mask_info *mask_info = NULL;
548
549 mask_info = (!info) ? &msg_mask : info->msg_mask;
550 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
551 !mask_info) {
552 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
553 __func__, src_buf, src_len, dest_buf, dest_len,
554 mask_info);
555 return -EINVAL;
556 }
557
558 if (!diag_apps_responds())
559 return 0;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530560 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700561 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
562 rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
563 rsp.status = MSG_STATUS_SUCCESS;
564 rsp.padding = 0;
565 rsp.count = driver->msg_mask_tbl_count;
566 memcpy(dest_buf, &rsp, sizeof(rsp));
567 write_len += sizeof(rsp);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700568 mask_ptr = (struct diag_msg_mask_t *)mask_info->ptr;
569 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask_ptr++) {
570 if (write_len + sizeof(ssid_range) > dest_len) {
571 pr_err("diag: In %s, Truncating response due to size limitations of rsp buffer\n",
572 __func__);
573 break;
574 }
575 ssid_range.ssid_first = mask_ptr->ssid_first;
576 ssid_range.ssid_last = mask_ptr->ssid_last_tools;
577 memcpy(dest_buf + write_len, &ssid_range, sizeof(ssid_range));
578 write_len += sizeof(ssid_range);
579 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530580 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700581 return write_len;
582}
583
584static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
585 unsigned char *dest_buf, int dest_len,
586 struct diag_md_session_t *info)
587{
588 int i = 0;
589 int write_len = 0;
590 int num_entries = 0;
591 int copy_len = 0;
592 struct diag_msg_mask_t *build_mask = NULL;
593 struct diag_build_mask_req_t *req = NULL;
594 struct diag_msg_build_mask_t rsp;
595
596 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
597 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
598 __func__, src_buf, src_len, dest_buf, dest_len);
599 return -EINVAL;
600 }
601
602 if (!diag_apps_responds())
603 return 0;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530604 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700605 req = (struct diag_build_mask_req_t *)src_buf;
606 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
607 rsp.sub_cmd = DIAG_CMD_OP_GET_BUILD_MASK;
608 rsp.ssid_first = req->ssid_first;
609 rsp.ssid_last = req->ssid_last;
610 rsp.status = MSG_STATUS_FAIL;
611 rsp.padding = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700612 build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530613 for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700614 if (build_mask->ssid_first != req->ssid_first)
615 continue;
616 num_entries = req->ssid_last - req->ssid_first + 1;
617 if (num_entries > build_mask->range) {
618 pr_warn("diag: In %s, truncating ssid range for ssid_first: %d ssid_last %d\n",
619 __func__, req->ssid_first, req->ssid_last);
620 num_entries = build_mask->range;
621 req->ssid_last = req->ssid_first + build_mask->range;
622 }
623 copy_len = num_entries * sizeof(uint32_t);
624 if (copy_len + sizeof(rsp) > dest_len)
625 copy_len = dest_len - sizeof(rsp);
626 memcpy(dest_buf + sizeof(rsp), build_mask->ptr, copy_len);
627 write_len += copy_len;
628 rsp.ssid_last = build_mask->ssid_last;
629 rsp.status = MSG_STATUS_SUCCESS;
630 break;
631 }
632 memcpy(dest_buf, &rsp, sizeof(rsp));
633 write_len += sizeof(rsp);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530634 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700635 return write_len;
636}
637
638static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
639 unsigned char *dest_buf, int dest_len,
640 struct diag_md_session_t *info)
641{
642 int i;
643 int write_len = 0;
644 uint32_t mask_size = 0;
645 struct diag_msg_mask_t *mask = NULL;
646 struct diag_build_mask_req_t *req = NULL;
647 struct diag_msg_build_mask_t rsp;
648 struct diag_mask_info *mask_info = NULL;
649
650 mask_info = (!info) ? &msg_mask : info->msg_mask;
651 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
652 !mask_info) {
653 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
654 __func__, src_buf, src_len, dest_buf, dest_len,
655 mask_info);
656 return -EINVAL;
657 }
658
659 if (!diag_apps_responds())
660 return 0;
661
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530662 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700663 req = (struct diag_build_mask_req_t *)src_buf;
664 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
665 rsp.sub_cmd = DIAG_CMD_OP_GET_MSG_MASK;
666 rsp.ssid_first = req->ssid_first;
667 rsp.ssid_last = req->ssid_last;
668 rsp.status = MSG_STATUS_FAIL;
669 rsp.padding = 0;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700670 mask = (struct diag_msg_mask_t *)mask_info->ptr;
671 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
672 if ((req->ssid_first < mask->ssid_first) ||
673 (req->ssid_first > mask->ssid_last_tools)) {
674 continue;
675 }
676 mask_size = mask->range * sizeof(uint32_t);
677 /* Copy msg mask only till the end of the rsp buffer */
678 if (mask_size + sizeof(rsp) > dest_len)
679 mask_size = dest_len - sizeof(rsp);
680 memcpy(dest_buf + sizeof(rsp), mask->ptr, mask_size);
681 write_len += mask_size;
682 rsp.status = MSG_STATUS_SUCCESS;
683 break;
684 }
685 memcpy(dest_buf, &rsp, sizeof(rsp));
686 write_len += sizeof(rsp);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530687 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700688 return write_len;
689}
690
691static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
692 unsigned char *dest_buf, int dest_len,
693 struct diag_md_session_t *info)
694{
695 int i;
696 int write_len = 0;
697 int header_len = sizeof(struct diag_msg_build_mask_t);
698 int found = 0;
699 uint32_t mask_size = 0;
700 uint32_t offset = 0;
701 struct diag_msg_mask_t *mask = NULL;
702 struct diag_msg_build_mask_t *req = NULL;
703 struct diag_msg_build_mask_t rsp;
704 struct diag_mask_info *mask_info = NULL;
705 struct diag_msg_mask_t *mask_next = NULL;
706 uint32_t *temp = NULL;
707
708 mask_info = (!info) ? &msg_mask : info->msg_mask;
709 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
710 !mask_info) {
711 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
712 __func__, src_buf, src_len, dest_buf, dest_len,
713 mask_info);
714 return -EINVAL;
715 }
716
717 req = (struct diag_msg_build_mask_t *)src_buf;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700718 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530719 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700720 mask = (struct diag_msg_mask_t *)mask_info->ptr;
721 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
722 if (i < (driver->msg_mask_tbl_count - 1)) {
723 mask_next = mask;
724 mask_next++;
725 } else
726 mask_next = NULL;
727
728 if ((req->ssid_first < mask->ssid_first) ||
729 (req->ssid_first > mask->ssid_first + MAX_SSID_PER_RANGE) ||
730 (mask_next && (req->ssid_first >= mask_next->ssid_first))) {
731 continue;
732 }
733 mask_next = NULL;
734 found = 1;
735 mutex_lock(&mask->lock);
736 mask_size = req->ssid_last - req->ssid_first + 1;
737 if (mask_size > MAX_SSID_PER_RANGE) {
738 pr_warn("diag: In %s, truncating ssid range, %d-%d to max allowed: %d\n",
739 __func__, mask->ssid_first, mask->ssid_last,
740 MAX_SSID_PER_RANGE);
741 mask_size = MAX_SSID_PER_RANGE;
742 mask->range_tools = MAX_SSID_PER_RANGE;
743 mask->ssid_last_tools =
744 mask->ssid_first + mask->range_tools;
745 }
746 if (req->ssid_last > mask->ssid_last_tools) {
747 pr_debug("diag: Msg SSID range mismatch\n");
748 if (mask_size != MAX_SSID_PER_RANGE)
749 mask->ssid_last_tools = req->ssid_last;
750 mask->range_tools =
751 mask->ssid_last_tools - mask->ssid_first + 1;
752 temp = krealloc(mask->ptr,
753 mask->range_tools * sizeof(uint32_t),
754 GFP_KERNEL);
755 if (!temp) {
756 pr_err_ratelimited("diag: In %s, unable to allocate memory for msg mask ptr, mask_size: %d\n",
757 __func__, mask_size);
758 mutex_unlock(&mask->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530759 mutex_unlock(&driver->msg_mask_lock);
760 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700761 return -ENOMEM;
762 }
763 mask->ptr = temp;
764 }
765
766 offset = req->ssid_first - mask->ssid_first;
767 if (offset + mask_size > mask->range_tools) {
768 pr_err("diag: In %s, Not in msg mask range, mask_size: %d, offset: %d\n",
769 __func__, mask_size, offset);
770 mutex_unlock(&mask->lock);
771 break;
772 }
773 mask_size = mask_size * sizeof(uint32_t);
774 memcpy(mask->ptr + offset, src_buf + header_len, mask_size);
775 mutex_unlock(&mask->lock);
776 mask_info->status = DIAG_CTRL_MASK_VALID;
777 break;
778 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530779 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530780 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700781 if (diag_check_update(APPS_DATA))
782 diag_update_userspace_clients(MSG_MASKS_TYPE);
783
784 /*
785 * Apps processor must send the response to this command. Frame the
786 * response.
787 */
788 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
789 rsp.sub_cmd = DIAG_CMD_OP_SET_MSG_MASK;
790 rsp.ssid_first = req->ssid_first;
791 rsp.ssid_last = req->ssid_last;
792 rsp.status = found;
793 rsp.padding = 0;
794 memcpy(dest_buf, &rsp, header_len);
795 write_len += header_len;
796 if (!found)
797 goto end;
798 if (mask_size + write_len > dest_len)
799 mask_size = dest_len - write_len;
800 memcpy(dest_buf + write_len, src_buf + header_len, mask_size);
801 write_len += mask_size;
802 for (i = 0; i < NUM_PERIPHERALS; i++) {
803 if (!diag_check_update(i))
804 continue;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530805 mutex_lock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700806 diag_send_msg_mask_update(i, req->ssid_first, req->ssid_last);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530807 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700808 }
809end:
810 return write_len;
811}
812
813static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
814 unsigned char *dest_buf, int dest_len,
815 struct diag_md_session_t *info)
816{
817 int i;
818 int write_len = 0;
819 int header_len = sizeof(struct diag_msg_config_rsp_t);
820 struct diag_msg_config_rsp_t rsp;
821 struct diag_msg_config_rsp_t *req = NULL;
822 struct diag_msg_mask_t *mask = NULL;
823 struct diag_mask_info *mask_info = NULL;
824
825 mask_info = (!info) ? &msg_mask : info->msg_mask;
826 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
827 !mask_info) {
828 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
829 __func__, src_buf, src_len, dest_buf, dest_len,
830 mask_info);
831 return -EINVAL;
832 }
833
834 req = (struct diag_msg_config_rsp_t *)src_buf;
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530835
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700836 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530837 mutex_lock(&driver->msg_mask_lock);
838
839 mask = (struct diag_msg_mask_t *)mask_info->ptr;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700840 mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
841 DIAG_CTRL_MASK_ALL_DISABLED;
842 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
843 mutex_lock(&mask->lock);
844 memset(mask->ptr, req->rt_mask,
845 mask->range * sizeof(uint32_t));
846 mutex_unlock(&mask->lock);
847 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +0530848 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +0530849 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700850
851 if (diag_check_update(APPS_DATA))
852 diag_update_userspace_clients(MSG_MASKS_TYPE);
853
854 /*
855 * Apps processor must send the response to this command. Frame the
856 * response.
857 */
858 rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
859 rsp.sub_cmd = DIAG_CMD_OP_SET_ALL_MSG_MASK;
860 rsp.status = MSG_STATUS_SUCCESS;
861 rsp.padding = 0;
862 rsp.rt_mask = req->rt_mask;
863 memcpy(dest_buf, &rsp, header_len);
864 write_len += header_len;
865
866 for (i = 0; i < NUM_PERIPHERALS; i++) {
867 if (!diag_check_update(i))
868 continue;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530869 mutex_lock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700870 diag_send_msg_mask_update(i, ALL_SSID, ALL_SSID);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530871 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700872 }
873
874 return write_len;
875}
876
877static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len,
878 unsigned char *dest_buf, int dest_len,
879 struct diag_md_session_t *info)
880{
881 int write_len = 0;
882 uint32_t mask_size;
883 struct diag_event_mask_config_t rsp;
884
885 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
886 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
887 __func__, src_buf, src_len, dest_buf, dest_len);
888 return -EINVAL;
889 }
890
891 if (!diag_apps_responds())
892 return 0;
893
894 mask_size = EVENT_COUNT_TO_BYTES(driver->last_event_id);
895 if (mask_size + sizeof(rsp) > dest_len) {
896 pr_err("diag: In %s, invalid mask size: %d\n", __func__,
897 mask_size);
898 return -ENOMEM;
899 }
900
901 rsp.cmd_code = DIAG_CMD_GET_EVENT_MASK;
902 rsp.status = EVENT_STATUS_SUCCESS;
903 rsp.padding = 0;
904 rsp.num_bits = driver->last_event_id + 1;
905 memcpy(dest_buf, &rsp, sizeof(rsp));
906 write_len += sizeof(rsp);
907 memcpy(dest_buf + write_len, event_mask.ptr, mask_size);
908 write_len += mask_size;
909
910 return write_len;
911}
912
913static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
914 unsigned char *dest_buf, int dest_len,
915 struct diag_md_session_t *info)
916{
917 int i;
918 int write_len = 0;
919 int mask_len = 0;
920 int header_len = sizeof(struct diag_event_mask_config_t);
921 struct diag_event_mask_config_t rsp;
922 struct diag_event_mask_config_t *req;
923 struct diag_mask_info *mask_info = NULL;
924
925 mask_info = (!info) ? &event_mask : info->event_mask;
926 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
927 !mask_info) {
928 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
929 __func__, src_buf, src_len, dest_buf, dest_len,
930 mask_info);
931 return -EINVAL;
932 }
933
934 req = (struct diag_event_mask_config_t *)src_buf;
935 mask_len = EVENT_COUNT_TO_BYTES(req->num_bits);
936 if (mask_len <= 0 || mask_len > event_mask.mask_len) {
937 pr_err("diag: In %s, invalid event mask len: %d\n", __func__,
938 mask_len);
939 return -EIO;
940 }
941
942 mutex_lock(&mask_info->lock);
943 memcpy(mask_info->ptr, src_buf + header_len, mask_len);
944 mask_info->status = DIAG_CTRL_MASK_VALID;
945 mutex_unlock(&mask_info->lock);
946 if (diag_check_update(APPS_DATA))
947 diag_update_userspace_clients(EVENT_MASKS_TYPE);
948
949 /*
950 * Apps processor must send the response to this command. Frame the
951 * response.
952 */
953 rsp.cmd_code = DIAG_CMD_SET_EVENT_MASK;
954 rsp.status = EVENT_STATUS_SUCCESS;
955 rsp.padding = 0;
956 rsp.num_bits = driver->last_event_id + 1;
957 memcpy(dest_buf, &rsp, header_len);
958 write_len += header_len;
959 memcpy(dest_buf + write_len, mask_info->ptr, mask_len);
960 write_len += mask_len;
961
962 for (i = 0; i < NUM_PERIPHERALS; i++) {
963 if (!diag_check_update(i))
964 continue;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530965 mutex_lock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700966 diag_send_event_mask_update(i);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +0530967 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -0700968 }
969
970 return write_len;
971}
972
973static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
974 unsigned char *dest_buf, int dest_len,
975 struct diag_md_session_t *info)
976{
977 int i;
978 int write_len = 0;
979 uint8_t toggle = 0;
980 struct diag_event_report_t header;
981 struct diag_mask_info *mask_info = NULL;
982
983 mask_info = (!info) ? &event_mask : info->event_mask;
984 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
985 !mask_info) {
986 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
987 __func__, src_buf, src_len, dest_buf, dest_len,
988 mask_info);
989 return -EINVAL;
990 }
991
992 toggle = *(src_buf + 1);
993 mutex_lock(&mask_info->lock);
994 if (toggle) {
995 mask_info->status = DIAG_CTRL_MASK_ALL_ENABLED;
996 memset(mask_info->ptr, 0xFF, mask_info->mask_len);
997 } else {
998 mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
999 memset(mask_info->ptr, 0, mask_info->mask_len);
1000 }
1001 mutex_unlock(&mask_info->lock);
1002 if (diag_check_update(APPS_DATA))
1003 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1004
1005 /*
1006 * Apps processor must send the response to this command. Frame the
1007 * response.
1008 */
1009 header.cmd_code = DIAG_CMD_EVENT_TOGGLE;
1010 header.padding = 0;
1011 for (i = 0; i < NUM_PERIPHERALS; i++) {
1012 if (!diag_check_update(i))
1013 continue;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301014 mutex_lock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001015 diag_send_event_mask_update(i);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301016 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001017 }
1018 memcpy(dest_buf, &header, sizeof(header));
1019 write_len += sizeof(header);
1020
1021 return write_len;
1022}
1023
1024static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
1025 unsigned char *dest_buf, int dest_len,
1026 struct diag_md_session_t *info)
1027{
1028 int i;
1029 int status = LOG_STATUS_INVALID;
1030 int write_len = 0;
1031 int read_len = 0;
1032 int req_header_len = sizeof(struct diag_log_config_req_t);
1033 int rsp_header_len = sizeof(struct diag_log_config_rsp_t);
1034 uint32_t mask_size = 0;
1035 struct diag_log_mask_t *log_item = NULL;
1036 struct diag_log_config_req_t *req;
1037 struct diag_log_config_rsp_t rsp;
1038 struct diag_mask_info *mask_info = NULL;
1039
1040 mask_info = (!info) ? &log_mask : info->log_mask;
1041 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1042 !mask_info) {
1043 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1044 __func__, src_buf, src_len, dest_buf, dest_len,
1045 mask_info);
1046 return -EINVAL;
1047 }
1048
1049 if (!diag_apps_responds())
1050 return 0;
1051
1052 req = (struct diag_log_config_req_t *)src_buf;
1053 read_len += req_header_len;
1054
1055 rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
1056 rsp.padding[0] = 0;
1057 rsp.padding[1] = 0;
1058 rsp.padding[2] = 0;
1059 rsp.sub_cmd = DIAG_CMD_OP_GET_LOG_MASK;
1060 /*
1061 * Don't copy the response header now. Copy at the end after
1062 * calculating the status field value
1063 */
1064 write_len += rsp_header_len;
1065
1066 log_item = (struct diag_log_mask_t *)mask_info->ptr;
1067 for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
1068 if (log_item->equip_id != req->equip_id)
1069 continue;
1070 mutex_lock(&log_item->lock);
1071 mask_size = LOG_ITEMS_TO_SIZE(log_item->num_items_tools);
1072 /*
1073 * Make sure we have space to fill the response in the buffer.
1074 * Destination buffer should atleast be able to hold equip_id
1075 * (uint32_t), num_items(uint32_t), mask (mask_size) and the
1076 * response header.
1077 */
1078 if ((mask_size + (2 * sizeof(uint32_t)) + rsp_header_len) >
1079 dest_len) {
1080 pr_err("diag: In %s, invalid length: %d, max rsp_len: %d\n",
1081 __func__, mask_size, dest_len);
1082 status = LOG_STATUS_FAIL;
1083 mutex_unlock(&log_item->lock);
1084 break;
1085 }
1086 *(uint32_t *)(dest_buf + write_len) = log_item->equip_id;
1087 write_len += sizeof(uint32_t);
1088 *(uint32_t *)(dest_buf + write_len) = log_item->num_items_tools;
1089 write_len += sizeof(uint32_t);
1090 if (mask_size > 0) {
1091 memcpy(dest_buf + write_len, log_item->ptr, mask_size);
1092 write_len += mask_size;
1093 }
1094 DIAG_LOG(DIAG_DEBUG_MASKS,
1095 "sending log e %d num_items %d size %d\n",
1096 log_item->equip_id, log_item->num_items_tools,
1097 log_item->range_tools);
1098 mutex_unlock(&log_item->lock);
1099 status = LOG_STATUS_SUCCESS;
1100 break;
1101 }
1102
1103 rsp.status = status;
1104 memcpy(dest_buf, &rsp, rsp_header_len);
1105
1106 return write_len;
1107}
1108
1109static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len,
1110 unsigned char *dest_buf, int dest_len,
1111 struct diag_md_session_t *info)
1112{
1113 int i;
1114 int write_len = 0;
1115 struct diag_log_config_rsp_t rsp;
1116 struct diag_mask_info *mask_info = NULL;
1117 struct diag_log_mask_t *mask = (struct diag_log_mask_t *)log_mask.ptr;
1118
1119 if (!diag_apps_responds())
1120 return 0;
1121
1122 mask_info = (!info) ? &log_mask : info->log_mask;
1123 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1124 !mask_info) {
1125 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1126 __func__, src_buf, src_len, dest_buf, dest_len,
1127 mask_info);
1128 return -EINVAL;
1129 }
1130
1131 rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
1132 rsp.padding[0] = 0;
1133 rsp.padding[1] = 0;
1134 rsp.padding[2] = 0;
1135 rsp.sub_cmd = DIAG_CMD_OP_GET_LOG_RANGE;
1136 rsp.status = LOG_STATUS_SUCCESS;
1137 memcpy(dest_buf, &rsp, sizeof(rsp));
1138 write_len += sizeof(rsp);
1139
1140 for (i = 0; i < MAX_EQUIP_ID && write_len < dest_len; i++, mask++) {
1141 *(uint32_t *)(dest_buf + write_len) = mask->num_items_tools;
1142 write_len += sizeof(uint32_t);
1143 }
1144
1145 return write_len;
1146}
1147
1148static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
1149 unsigned char *dest_buf, int dest_len,
1150 struct diag_md_session_t *info)
1151{
1152 int i;
1153 int write_len = 0;
1154 int status = LOG_STATUS_SUCCESS;
1155 int read_len = 0;
1156 int payload_len = 0;
1157 int req_header_len = sizeof(struct diag_log_config_req_t);
1158 int rsp_header_len = sizeof(struct diag_log_config_set_rsp_t);
1159 uint32_t mask_size = 0;
1160 struct diag_log_config_req_t *req;
1161 struct diag_log_config_set_rsp_t rsp;
1162 struct diag_log_mask_t *mask = NULL;
1163 unsigned char *temp_buf = NULL;
1164 struct diag_mask_info *mask_info = NULL;
1165
1166 mask_info = (!info) ? &log_mask : info->log_mask;
1167 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1168 !mask_info) {
1169 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1170 __func__, src_buf, src_len, dest_buf, dest_len,
1171 mask_info);
1172 return -EINVAL;
1173 }
1174
1175 req = (struct diag_log_config_req_t *)src_buf;
1176 read_len += req_header_len;
1177 mask = (struct diag_log_mask_t *)mask_info->ptr;
1178
1179 if (req->equip_id >= MAX_EQUIP_ID) {
1180 pr_err("diag: In %s, Invalid logging mask request, equip_id: %d\n",
1181 __func__, req->equip_id);
1182 status = LOG_STATUS_INVALID;
1183 }
1184
1185 if (req->num_items == 0) {
1186 pr_err("diag: In %s, Invalid number of items in log mask request, equip_id: %d\n",
1187 __func__, req->equip_id);
1188 status = LOG_STATUS_INVALID;
1189 }
1190
1191 mutex_lock(&mask_info->lock);
1192 for (i = 0; i < MAX_EQUIP_ID && !status; i++, mask++) {
1193 if (mask->equip_id != req->equip_id)
1194 continue;
1195 mutex_lock(&mask->lock);
1196
1197 DIAG_LOG(DIAG_DEBUG_MASKS, "e: %d current: %d %d new: %d %d",
1198 mask->equip_id, mask->num_items_tools,
1199 mask->range_tools, req->num_items,
1200 LOG_ITEMS_TO_SIZE(req->num_items));
1201 /*
1202 * If the size of the log mask cannot fit into our
1203 * buffer, trim till we have space left in the buffer.
1204 * num_items should then reflect the items that we have
1205 * in our buffer.
1206 */
1207 mask->num_items_tools = (req->num_items > MAX_ITEMS_ALLOWED) ?
1208 MAX_ITEMS_ALLOWED : req->num_items;
1209 mask_size = LOG_ITEMS_TO_SIZE(mask->num_items_tools);
1210 memset(mask->ptr, 0, mask->range_tools);
1211 if (mask_size > mask->range_tools) {
1212 DIAG_LOG(DIAG_DEBUG_MASKS,
1213 "log range mismatch, e: %d old: %d new: %d\n",
1214 req->equip_id, mask->range_tools,
1215 LOG_ITEMS_TO_SIZE(mask->num_items_tools));
1216 /* Change in the mask reported by tools */
1217 temp_buf = krealloc(mask->ptr, mask_size, GFP_KERNEL);
1218 if (!temp_buf) {
1219 mask_info->status = DIAG_CTRL_MASK_INVALID;
1220 mutex_unlock(&mask->lock);
1221 break;
1222 }
1223 mask->ptr = temp_buf;
1224 memset(mask->ptr, 0, mask_size);
1225 mask->range_tools = mask_size;
1226 }
1227 req->num_items = mask->num_items_tools;
1228 if (mask_size > 0)
1229 memcpy(mask->ptr, src_buf + read_len, mask_size);
1230 DIAG_LOG(DIAG_DEBUG_MASKS,
1231 "copying log mask, e %d num %d range %d size %d\n",
1232 req->equip_id, mask->num_items_tools,
1233 mask->range_tools, mask_size);
1234 mutex_unlock(&mask->lock);
1235 mask_info->status = DIAG_CTRL_MASK_VALID;
1236 break;
1237 }
1238 mutex_unlock(&mask_info->lock);
1239 if (diag_check_update(APPS_DATA))
1240 diag_update_userspace_clients(LOG_MASKS_TYPE);
1241
1242 /*
1243 * Apps processor must send the response to this command. Frame the
1244 * response.
1245 */
1246 payload_len = LOG_ITEMS_TO_SIZE(req->num_items);
1247 if ((payload_len + rsp_header_len > dest_len) || (payload_len == 0)) {
1248 pr_err("diag: In %s, invalid length, payload_len: %d, header_len: %d, dest_len: %d\n",
1249 __func__, payload_len, rsp_header_len, dest_len);
1250 status = LOG_STATUS_FAIL;
1251 }
1252 rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
1253 rsp.padding[0] = 0;
1254 rsp.padding[1] = 0;
1255 rsp.padding[2] = 0;
1256 rsp.sub_cmd = DIAG_CMD_OP_SET_LOG_MASK;
1257 rsp.status = status;
1258 rsp.equip_id = req->equip_id;
1259 rsp.num_items = req->num_items;
1260 memcpy(dest_buf, &rsp, rsp_header_len);
1261 write_len += rsp_header_len;
1262 if (status != LOG_STATUS_SUCCESS)
1263 goto end;
1264 memcpy(dest_buf + write_len, src_buf + read_len, payload_len);
1265 write_len += payload_len;
1266
1267 for (i = 0; i < NUM_PERIPHERALS; i++) {
1268 if (!diag_check_update(i))
1269 continue;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301270 mutex_lock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001271 diag_send_log_mask_update(i, req->equip_id);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301272 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001273 }
1274end:
1275 return write_len;
1276}
1277
1278static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
1279 unsigned char *dest_buf, int dest_len,
1280 struct diag_md_session_t *info)
1281{
1282 struct diag_mask_info *mask_info = NULL;
1283 struct diag_log_mask_t *mask = NULL;
1284 struct diag_log_config_rsp_t header;
1285 int write_len = 0;
1286 int i;
1287
1288 mask_info = (!info) ? &log_mask : info->log_mask;
1289 if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
1290 !mask_info) {
1291 pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
1292 __func__, src_buf, src_len, dest_buf, dest_len,
1293 mask_info);
1294 return -EINVAL;
1295 }
1296
1297 mask = (struct diag_log_mask_t *)mask_info->ptr;
1298
1299 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1300 mutex_lock(&mask->lock);
1301 memset(mask->ptr, 0, mask->range);
1302 mutex_unlock(&mask->lock);
1303 }
1304 mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
1305 if (diag_check_update(APPS_DATA))
1306 diag_update_userspace_clients(LOG_MASKS_TYPE);
1307
1308 /*
1309 * Apps processor must send the response to this command. Frame the
1310 * response.
1311 */
1312 header.cmd_code = DIAG_CMD_LOG_CONFIG;
1313 header.padding[0] = 0;
1314 header.padding[1] = 0;
1315 header.padding[2] = 0;
1316 header.sub_cmd = DIAG_CMD_OP_LOG_DISABLE;
1317 header.status = LOG_STATUS_SUCCESS;
1318 memcpy(dest_buf, &header, sizeof(struct diag_log_config_rsp_t));
1319 write_len += sizeof(struct diag_log_config_rsp_t);
1320 for (i = 0; i < NUM_PERIPHERALS; i++) {
1321 if (!diag_check_update(i))
1322 continue;
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301323 mutex_lock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001324 diag_send_log_mask_update(i, ALL_EQUIP_ID);
Mohit Aggarwalb47931f2017-07-05 15:54:28 +05301325 mutex_unlock(&driver->md_session_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001326 }
1327
1328 return write_len;
1329}
1330
1331int diag_create_msg_mask_table_entry(struct diag_msg_mask_t *msg_mask,
1332 struct diag_ssid_range_t *range)
1333{
1334 if (!msg_mask || !range)
1335 return -EIO;
1336 if (range->ssid_last < range->ssid_first)
1337 return -EINVAL;
1338 msg_mask->ssid_first = range->ssid_first;
1339 msg_mask->ssid_last = range->ssid_last;
1340 msg_mask->ssid_last_tools = range->ssid_last;
1341 msg_mask->range = msg_mask->ssid_last - msg_mask->ssid_first + 1;
1342 if (msg_mask->range < MAX_SSID_PER_RANGE)
1343 msg_mask->range = MAX_SSID_PER_RANGE;
1344 msg_mask->range_tools = msg_mask->range;
1345 mutex_init(&msg_mask->lock);
1346 if (msg_mask->range > 0) {
1347 msg_mask->ptr = kcalloc(msg_mask->range, sizeof(uint32_t),
1348 GFP_KERNEL);
1349 if (!msg_mask->ptr)
1350 return -ENOMEM;
1351 kmemleak_not_leak(msg_mask->ptr);
1352 }
1353 return 0;
1354}
1355
1356static int diag_create_msg_mask_table(void)
1357{
1358 int i;
1359 int err = 0;
1360 struct diag_msg_mask_t *mask = (struct diag_msg_mask_t *)msg_mask.ptr;
1361 struct diag_ssid_range_t range;
1362
1363 mutex_lock(&msg_mask.lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301364 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001365 driver->msg_mask_tbl_count = MSG_MASK_TBL_CNT;
1366 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
1367 range.ssid_first = msg_mask_tbl[i].ssid_first;
1368 range.ssid_last = msg_mask_tbl[i].ssid_last;
1369 err = diag_create_msg_mask_table_entry(mask, &range);
1370 if (err)
1371 break;
1372 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301373 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301374 mutex_unlock(&msg_mask.lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001375 return err;
1376}
1377
1378static int diag_create_build_time_mask(void)
1379{
1380 int i;
1381 int err = 0;
1382 const uint32_t *tbl = NULL;
1383 uint32_t tbl_size = 0;
1384 struct diag_msg_mask_t *build_mask = NULL;
1385 struct diag_ssid_range_t range;
1386
1387 mutex_lock(&msg_bt_mask.lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301388 mutex_lock(&driver->msg_mask_lock);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301389 driver->bt_msg_mask_tbl_count = MSG_MASK_TBL_CNT;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001390 build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301391 for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001392 range.ssid_first = msg_mask_tbl[i].ssid_first;
1393 range.ssid_last = msg_mask_tbl[i].ssid_last;
1394 err = diag_create_msg_mask_table_entry(build_mask, &range);
1395 if (err)
1396 break;
1397 switch (build_mask->ssid_first) {
1398 case MSG_SSID_0:
1399 tbl = msg_bld_masks_0;
1400 tbl_size = sizeof(msg_bld_masks_0);
1401 break;
1402 case MSG_SSID_1:
1403 tbl = msg_bld_masks_1;
1404 tbl_size = sizeof(msg_bld_masks_1);
1405 break;
1406 case MSG_SSID_2:
1407 tbl = msg_bld_masks_2;
1408 tbl_size = sizeof(msg_bld_masks_2);
1409 break;
1410 case MSG_SSID_3:
1411 tbl = msg_bld_masks_3;
1412 tbl_size = sizeof(msg_bld_masks_3);
1413 break;
1414 case MSG_SSID_4:
1415 tbl = msg_bld_masks_4;
1416 tbl_size = sizeof(msg_bld_masks_4);
1417 break;
1418 case MSG_SSID_5:
1419 tbl = msg_bld_masks_5;
1420 tbl_size = sizeof(msg_bld_masks_5);
1421 break;
1422 case MSG_SSID_6:
1423 tbl = msg_bld_masks_6;
1424 tbl_size = sizeof(msg_bld_masks_6);
1425 break;
1426 case MSG_SSID_7:
1427 tbl = msg_bld_masks_7;
1428 tbl_size = sizeof(msg_bld_masks_7);
1429 break;
1430 case MSG_SSID_8:
1431 tbl = msg_bld_masks_8;
1432 tbl_size = sizeof(msg_bld_masks_8);
1433 break;
1434 case MSG_SSID_9:
1435 tbl = msg_bld_masks_9;
1436 tbl_size = sizeof(msg_bld_masks_9);
1437 break;
1438 case MSG_SSID_10:
1439 tbl = msg_bld_masks_10;
1440 tbl_size = sizeof(msg_bld_masks_10);
1441 break;
1442 case MSG_SSID_11:
1443 tbl = msg_bld_masks_11;
1444 tbl_size = sizeof(msg_bld_masks_11);
1445 break;
1446 case MSG_SSID_12:
1447 tbl = msg_bld_masks_12;
1448 tbl_size = sizeof(msg_bld_masks_12);
1449 break;
1450 case MSG_SSID_13:
1451 tbl = msg_bld_masks_13;
1452 tbl_size = sizeof(msg_bld_masks_13);
1453 break;
1454 case MSG_SSID_14:
1455 tbl = msg_bld_masks_14;
1456 tbl_size = sizeof(msg_bld_masks_14);
1457 break;
1458 case MSG_SSID_15:
1459 tbl = msg_bld_masks_15;
1460 tbl_size = sizeof(msg_bld_masks_15);
1461 break;
1462 case MSG_SSID_16:
1463 tbl = msg_bld_masks_16;
1464 tbl_size = sizeof(msg_bld_masks_16);
1465 break;
1466 case MSG_SSID_17:
1467 tbl = msg_bld_masks_17;
1468 tbl_size = sizeof(msg_bld_masks_17);
1469 break;
1470 case MSG_SSID_18:
1471 tbl = msg_bld_masks_18;
1472 tbl_size = sizeof(msg_bld_masks_18);
1473 break;
1474 case MSG_SSID_19:
1475 tbl = msg_bld_masks_19;
1476 tbl_size = sizeof(msg_bld_masks_19);
1477 break;
1478 case MSG_SSID_20:
1479 tbl = msg_bld_masks_20;
1480 tbl_size = sizeof(msg_bld_masks_20);
1481 break;
1482 case MSG_SSID_21:
1483 tbl = msg_bld_masks_21;
1484 tbl_size = sizeof(msg_bld_masks_21);
1485 break;
1486 case MSG_SSID_22:
1487 tbl = msg_bld_masks_22;
1488 tbl_size = sizeof(msg_bld_masks_22);
1489 break;
1490 }
1491 if (!tbl)
1492 continue;
1493 if (tbl_size > build_mask->range * sizeof(uint32_t)) {
1494 pr_warn("diag: In %s, table %d has more ssid than max, ssid_first: %d, ssid_last: %d\n",
1495 __func__, i, build_mask->ssid_first,
1496 build_mask->ssid_last);
1497 tbl_size = build_mask->range * sizeof(uint32_t);
1498 }
1499 memcpy(build_mask->ptr, tbl, tbl_size);
1500 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301501 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301502 mutex_unlock(&msg_bt_mask.lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001503 return err;
1504}
1505
1506static int diag_create_log_mask_table(void)
1507{
1508 struct diag_log_mask_t *mask = NULL;
1509 uint8_t i;
1510 int err = 0;
1511
1512 mutex_lock(&log_mask.lock);
1513 mask = (struct diag_log_mask_t *)(log_mask.ptr);
1514 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1515 mask->equip_id = i;
1516 mask->num_items = LOG_GET_ITEM_NUM(log_code_last_tbl[i]);
1517 mask->num_items_tools = mask->num_items;
1518 mutex_init(&mask->lock);
1519 if (LOG_ITEMS_TO_SIZE(mask->num_items) > MAX_ITEMS_PER_EQUIP_ID)
1520 mask->range = LOG_ITEMS_TO_SIZE(mask->num_items);
1521 else
1522 mask->range = MAX_ITEMS_PER_EQUIP_ID;
1523 mask->range_tools = mask->range;
1524 mask->ptr = kzalloc(mask->range, GFP_KERNEL);
1525 if (!mask->ptr) {
1526 err = -ENOMEM;
1527 break;
1528 }
1529 kmemleak_not_leak(mask->ptr);
1530 }
1531 mutex_unlock(&log_mask.lock);
1532 return err;
1533}
1534
1535static int __diag_mask_init(struct diag_mask_info *mask_info, int mask_len,
1536 int update_buf_len)
1537{
1538 if (!mask_info || mask_len < 0 || update_buf_len < 0)
1539 return -EINVAL;
1540
1541 mask_info->status = DIAG_CTRL_MASK_INVALID;
1542 mask_info->mask_len = mask_len;
1543 mask_info->update_buf_len = update_buf_len;
1544 if (mask_len > 0) {
1545 mask_info->ptr = kzalloc(mask_len, GFP_KERNEL);
1546 if (!mask_info->ptr)
1547 return -ENOMEM;
1548 kmemleak_not_leak(mask_info->ptr);
1549 }
1550 if (update_buf_len > 0) {
1551 mask_info->update_buf = kzalloc(update_buf_len, GFP_KERNEL);
1552 if (!mask_info->update_buf) {
1553 kfree(mask_info->ptr);
1554 return -ENOMEM;
1555 }
1556 kmemleak_not_leak(mask_info->update_buf);
1557 }
1558 mutex_init(&mask_info->lock);
1559 return 0;
1560}
1561
1562static void __diag_mask_exit(struct diag_mask_info *mask_info)
1563{
1564 if (!mask_info)
1565 return;
1566
1567 mutex_lock(&mask_info->lock);
1568 kfree(mask_info->ptr);
1569 mask_info->ptr = NULL;
1570 kfree(mask_info->update_buf);
1571 mask_info->update_buf = NULL;
1572 mutex_unlock(&mask_info->lock);
1573}
1574
1575int diag_log_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
1576{
1577 int i;
1578 int err = 0;
1579 struct diag_log_mask_t *src_mask = NULL;
1580 struct diag_log_mask_t *dest_mask = NULL;
1581
1582 if (!src)
1583 return -EINVAL;
1584
1585 err = __diag_mask_init(dest, LOG_MASK_SIZE, APPS_BUF_SIZE);
1586 if (err)
1587 return err;
1588
1589 mutex_lock(&dest->lock);
1590 src_mask = (struct diag_log_mask_t *)(src->ptr);
1591 dest_mask = (struct diag_log_mask_t *)(dest->ptr);
1592
1593 dest->mask_len = src->mask_len;
1594 dest->status = src->status;
1595
1596 for (i = 0; i < MAX_EQUIP_ID; i++, src_mask++, dest_mask++) {
1597 dest_mask->equip_id = src_mask->equip_id;
1598 dest_mask->num_items = src_mask->num_items;
1599 dest_mask->num_items_tools = src_mask->num_items_tools;
1600 mutex_init(&dest_mask->lock);
1601 dest_mask->range = src_mask->range;
1602 dest_mask->range_tools = src_mask->range_tools;
1603 dest_mask->ptr = kzalloc(dest_mask->range_tools, GFP_KERNEL);
1604 if (!dest_mask->ptr) {
1605 err = -ENOMEM;
1606 break;
1607 }
1608 kmemleak_not_leak(dest_mask->ptr);
1609 memcpy(dest_mask->ptr, src_mask->ptr, dest_mask->range_tools);
1610 }
1611 mutex_unlock(&dest->lock);
1612
1613 return err;
1614}
1615
1616void diag_log_mask_free(struct diag_mask_info *mask_info)
1617{
1618 int i;
1619 struct diag_log_mask_t *mask = NULL;
1620
1621 if (!mask_info)
1622 return;
1623
1624 mutex_lock(&mask_info->lock);
1625 mask = (struct diag_log_mask_t *)mask_info->ptr;
1626 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1627 kfree(mask->ptr);
1628 mask->ptr = NULL;
1629 }
1630 mutex_unlock(&mask_info->lock);
1631
1632 __diag_mask_exit(mask_info);
1633
1634}
1635
1636static int diag_msg_mask_init(void)
1637{
1638 int err = 0;
1639 int i;
1640
1641 err = __diag_mask_init(&msg_mask, MSG_MASK_SIZE, APPS_BUF_SIZE);
1642 if (err)
1643 return err;
1644 err = diag_create_msg_mask_table();
1645 if (err) {
1646 pr_err("diag: Unable to create msg masks, err: %d\n", err);
1647 return err;
1648 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301649 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001650 driver->msg_mask = &msg_mask;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001651 for (i = 0; i < NUM_PERIPHERALS; i++)
1652 driver->max_ssid_count[i] = 0;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301653 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001654
1655 return 0;
1656}
1657
1658int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
1659{
1660 int i;
1661 int err = 0;
1662 struct diag_msg_mask_t *src_mask = NULL;
1663 struct diag_msg_mask_t *dest_mask = NULL;
1664 struct diag_ssid_range_t range;
1665
1666 if (!src || !dest)
1667 return -EINVAL;
1668
1669 err = __diag_mask_init(dest, MSG_MASK_SIZE, APPS_BUF_SIZE);
1670 if (err)
1671 return err;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001672 mutex_lock(&dest->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301673 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001674 src_mask = (struct diag_msg_mask_t *)src->ptr;
1675 dest_mask = (struct diag_msg_mask_t *)dest->ptr;
1676
1677 dest->mask_len = src->mask_len;
1678 dest->status = src->status;
1679 for (i = 0; i < driver->msg_mask_tbl_count; i++) {
1680 range.ssid_first = src_mask->ssid_first;
1681 range.ssid_last = src_mask->ssid_last;
1682 err = diag_create_msg_mask_table_entry(dest_mask, &range);
1683 if (err)
1684 break;
1685 memcpy(dest_mask->ptr, src_mask->ptr,
1686 dest_mask->range * sizeof(uint32_t));
1687 src_mask++;
1688 dest_mask++;
1689 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301690 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301691 mutex_unlock(&dest->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001692 return err;
1693}
1694
1695void diag_msg_mask_free(struct diag_mask_info *mask_info)
1696{
1697 int i;
1698 struct diag_msg_mask_t *mask = NULL;
1699
1700 if (!mask_info)
1701 return;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001702 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301703 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001704 mask = (struct diag_msg_mask_t *)mask_info->ptr;
1705 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
1706 kfree(mask->ptr);
1707 mask->ptr = NULL;
1708 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301709 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301710 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001711 __diag_mask_exit(mask_info);
1712}
1713
1714static void diag_msg_mask_exit(void)
1715{
1716 int i;
1717 struct diag_msg_mask_t *mask = NULL;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301718 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001719 mask = (struct diag_msg_mask_t *)(msg_mask.ptr);
1720 if (mask) {
1721 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++)
1722 kfree(mask->ptr);
1723 kfree(msg_mask.ptr);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301724 msg_mask.ptr = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001725 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001726 kfree(msg_mask.update_buf);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301727 msg_mask.update_buf = NULL;
1728 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001729}
1730
1731static int diag_build_time_mask_init(void)
1732{
1733 int err = 0;
1734
1735 /* There is no need for update buffer for Build Time masks */
1736 err = __diag_mask_init(&msg_bt_mask, MSG_MASK_SIZE, 0);
1737 if (err)
1738 return err;
1739 err = diag_create_build_time_mask();
1740 if (err) {
1741 pr_err("diag: Unable to create msg build time masks, err: %d\n",
1742 err);
1743 return err;
1744 }
1745 driver->build_time_mask = &msg_bt_mask;
1746 return 0;
1747}
1748
1749static void diag_build_time_mask_exit(void)
1750{
1751 int i;
1752 struct diag_msg_mask_t *mask = NULL;
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301753 mutex_lock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001754 mask = (struct diag_msg_mask_t *)(msg_bt_mask.ptr);
1755 if (mask) {
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301756 for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, mask++)
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001757 kfree(mask->ptr);
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301758 kfree(msg_bt_mask.ptr);
1759 msg_bt_mask.ptr = NULL;
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001760 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301761 mutex_unlock(&driver->msg_mask_lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001762}
1763
1764static int diag_log_mask_init(void)
1765{
1766 int err = 0;
1767 int i;
1768
1769 err = __diag_mask_init(&log_mask, LOG_MASK_SIZE, APPS_BUF_SIZE);
1770 if (err)
1771 return err;
1772 err = diag_create_log_mask_table();
1773 if (err)
1774 return err;
1775 driver->log_mask = &log_mask;
1776
1777 for (i = 0; i < NUM_PERIPHERALS; i++)
1778 driver->num_equip_id[i] = 0;
1779
1780 return 0;
1781}
1782
1783static void diag_log_mask_exit(void)
1784{
1785 int i;
1786 struct diag_log_mask_t *mask = NULL;
1787
1788 mask = (struct diag_log_mask_t *)(log_mask.ptr);
1789 if (mask) {
1790 for (i = 0; i < MAX_EQUIP_ID; i++, mask++)
1791 kfree(mask->ptr);
1792 kfree(log_mask.ptr);
1793 }
1794
1795 kfree(log_mask.update_buf);
1796}
1797
1798static int diag_event_mask_init(void)
1799{
1800 int err = 0;
1801 int i;
1802
1803 err = __diag_mask_init(&event_mask, EVENT_MASK_SIZE, APPS_BUF_SIZE);
1804 if (err)
1805 return err;
1806 driver->event_mask_size = EVENT_MASK_SIZE;
1807 driver->last_event_id = APPS_EVENT_LAST_ID;
1808 driver->event_mask = &event_mask;
1809
1810 for (i = 0; i < NUM_PERIPHERALS; i++)
1811 driver->num_event_id[i] = 0;
1812
1813 return 0;
1814}
1815
1816int diag_event_mask_copy(struct diag_mask_info *dest,
1817 struct diag_mask_info *src)
1818{
1819 int err = 0;
1820
1821 if (!src || !dest)
1822 return -EINVAL;
1823
1824 err = __diag_mask_init(dest, EVENT_MASK_SIZE, APPS_BUF_SIZE);
1825 if (err)
1826 return err;
1827
1828 mutex_lock(&dest->lock);
1829 dest->mask_len = src->mask_len;
1830 dest->status = src->status;
1831 memcpy(dest->ptr, src->ptr, dest->mask_len);
1832 mutex_unlock(&dest->lock);
1833
1834 return err;
1835}
1836
1837void diag_event_mask_free(struct diag_mask_info *mask_info)
1838{
1839 if (!mask_info)
1840 return;
1841
1842 __diag_mask_exit(mask_info);
1843}
1844
1845static void diag_event_mask_exit(void)
1846{
1847 kfree(event_mask.ptr);
1848 kfree(event_mask.update_buf);
1849}
1850
1851int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
1852 struct diag_md_session_t *info)
1853{
1854 int i;
1855 int err = 0;
1856 int len = 0;
1857 int copy_len = 0;
1858 int total_len = 0;
1859 struct diag_msg_mask_userspace_t header;
1860 struct diag_mask_info *mask_info = NULL;
1861 struct diag_msg_mask_t *mask = NULL;
1862 unsigned char *ptr = NULL;
1863
1864 if (!buf || count == 0)
1865 return -EINVAL;
1866
1867 mask_info = (!info) ? &msg_mask : info->msg_mask;
1868 if (!mask_info)
1869 return -EIO;
1870
1871 mutex_lock(&driver->diag_maskclear_mutex);
1872 if (driver->mask_clear) {
1873 DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
1874 "diag:%s: count = %zu\n", __func__, count);
1875 mutex_unlock(&driver->diag_maskclear_mutex);
1876 return -EIO;
1877 }
1878 mutex_unlock(&driver->diag_maskclear_mutex);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001879 mutex_lock(&mask_info->lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301880 mutex_lock(&driver->msg_mask_lock);
1881
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001882 mask = (struct diag_msg_mask_t *)(mask_info->ptr);
1883 for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
1884 ptr = mask_info->update_buf;
1885 len = 0;
1886 mutex_lock(&mask->lock);
1887 header.ssid_first = mask->ssid_first;
1888 header.ssid_last = mask->ssid_last_tools;
1889 header.range = mask->range_tools;
1890 memcpy(ptr, &header, sizeof(header));
1891 len += sizeof(header);
1892 copy_len = (sizeof(uint32_t) * mask->range_tools);
1893 if ((len + copy_len) > mask_info->update_buf_len) {
1894 pr_err("diag: In %s, no space to update msg mask, first: %d, last: %d\n",
1895 __func__, mask->ssid_first,
1896 mask->ssid_last_tools);
1897 mutex_unlock(&mask->lock);
1898 continue;
1899 }
1900 memcpy(ptr + len, mask->ptr, copy_len);
1901 len += copy_len;
1902 mutex_unlock(&mask->lock);
1903 /* + sizeof(int) to account for data_type already in buf */
1904 if (total_len + sizeof(int) + len > count) {
1905 pr_err("diag: In %s, unable to send msg masks to user space, total_len: %d, count: %zu\n",
1906 __func__, total_len, count);
1907 err = -ENOMEM;
1908 break;
1909 }
1910 err = copy_to_user(buf + total_len, (void *)ptr, len);
1911 if (err) {
1912 pr_err("diag: In %s Unable to send msg masks to user space clients, err: %d\n",
1913 __func__, err);
1914 break;
1915 }
1916 total_len += len;
1917 }
Gopikrishna Mogasati9a44d8d2017-05-05 16:04:35 +05301918 mutex_unlock(&driver->msg_mask_lock);
Manoj Prabhu Be68c27a2017-07-14 16:52:45 +05301919 mutex_unlock(&mask_info->lock);
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07001920 return err ? err : total_len;
1921}
1922
1923int diag_copy_to_user_log_mask(char __user *buf, size_t count,
1924 struct diag_md_session_t *info)
1925{
1926 int i;
1927 int err = 0;
1928 int len = 0;
1929 int copy_len = 0;
1930 int total_len = 0;
1931 struct diag_log_mask_userspace_t header;
1932 struct diag_log_mask_t *mask = NULL;
1933 struct diag_mask_info *mask_info = NULL;
1934 unsigned char *ptr = NULL;
1935
1936 if (!buf || count == 0)
1937 return -EINVAL;
1938
1939 mask_info = (!info) ? &log_mask : info->log_mask;
1940 if (!mask_info)
1941 return -EIO;
1942
1943 mutex_lock(&mask_info->lock);
1944 mask = (struct diag_log_mask_t *)(mask_info->ptr);
1945 for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
1946 ptr = mask_info->update_buf;
1947 len = 0;
1948 mutex_lock(&mask->lock);
1949 header.equip_id = mask->equip_id;
1950 header.num_items = mask->num_items_tools;
1951 memcpy(ptr, &header, sizeof(header));
1952 len += sizeof(header);
1953 copy_len = LOG_ITEMS_TO_SIZE(header.num_items);
1954 if ((len + copy_len) > mask_info->update_buf_len) {
1955 pr_err("diag: In %s, no space to update log mask, equip_id: %d\n",
1956 __func__, mask->equip_id);
1957 mutex_unlock(&mask->lock);
1958 continue;
1959 }
1960 memcpy(ptr + len, mask->ptr, copy_len);
1961 len += copy_len;
1962 mutex_unlock(&mask->lock);
1963 /* + sizeof(int) to account for data_type already in buf */
1964 if (total_len + sizeof(int) + len > count) {
1965 pr_err("diag: In %s, unable to send log masks to user space, total_len: %d, count: %zu\n",
1966 __func__, total_len, count);
1967 err = -ENOMEM;
1968 break;
1969 }
1970 err = copy_to_user(buf + total_len, (void *)ptr, len);
1971 if (err) {
1972 pr_err("diag: In %s Unable to send log masks to user space clients, err: %d\n",
1973 __func__, err);
1974 break;
1975 }
1976 total_len += len;
1977 }
1978 mutex_unlock(&mask_info->lock);
1979
1980 return err ? err : total_len;
1981}
1982
1983void diag_send_updates_peripheral(uint8_t peripheral)
1984{
1985 diag_send_feature_mask_update(peripheral);
Manoj Prabhu B571cf422017-08-08 19:01:41 +05301986 /*
1987 * Masks (F3, logs and events) will be sent to
1988 * peripheral immediately following feature mask update only
1989 * if diag_id support is not present or
1990 * diag_id support is present and diag_id has been sent to
1991 * peripheral.
1992 */
1993 if (!driver->feature[peripheral].diag_id_support ||
1994 driver->diag_id_sent[peripheral]) {
1995 if (driver->time_sync_enabled)
1996 diag_send_time_sync_update(peripheral);
1997 mutex_lock(&driver->md_session_lock);
1998 diag_send_msg_mask_update(peripheral, ALL_SSID, ALL_SSID);
1999 diag_send_log_mask_update(peripheral, ALL_EQUIP_ID);
2000 diag_send_event_mask_update(peripheral);
2001 mutex_unlock(&driver->md_session_lock);
2002 diag_send_real_time_update(peripheral,
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002003 driver->real_time_mode[DIAG_LOCAL_PROC]);
Manoj Prabhu B571cf422017-08-08 19:01:41 +05302004 diag_send_peripheral_buffering_mode(
2005 &driver->buffering_mode[peripheral]);
2006 }
Sreelakshmi Gownipallicb8893d2016-10-19 16:02:34 -07002007}
2008
2009int diag_process_apps_masks(unsigned char *buf, int len,
2010 struct diag_md_session_t *info)
2011{
2012 int size = 0;
2013 int sub_cmd = 0;
2014 int (*hdlr)(unsigned char *src_buf, int src_len,
2015 unsigned char *dest_buf, int dest_len,
2016 struct diag_md_session_t *info) = NULL;
2017
2018 if (!buf || len <= 0)
2019 return -EINVAL;
2020
2021 if (*buf == DIAG_CMD_LOG_CONFIG) {
2022 sub_cmd = *(int *)(buf + sizeof(int));
2023 switch (sub_cmd) {
2024 case DIAG_CMD_OP_LOG_DISABLE:
2025 hdlr = diag_cmd_disable_log_mask;
2026 break;
2027 case DIAG_CMD_OP_GET_LOG_RANGE:
2028 hdlr = diag_cmd_get_log_range;
2029 break;
2030 case DIAG_CMD_OP_SET_LOG_MASK:
2031 hdlr = diag_cmd_set_log_mask;
2032 break;
2033 case DIAG_CMD_OP_GET_LOG_MASK:
2034 hdlr = diag_cmd_get_log_mask;
2035 break;
2036 }
2037 } else if (*buf == DIAG_CMD_MSG_CONFIG) {
2038 sub_cmd = *(uint8_t *)(buf + sizeof(uint8_t));
2039 switch (sub_cmd) {
2040 case DIAG_CMD_OP_GET_SSID_RANGE:
2041 hdlr = diag_cmd_get_ssid_range;
2042 break;
2043 case DIAG_CMD_OP_GET_BUILD_MASK:
2044 hdlr = diag_cmd_get_build_mask;
2045 break;
2046 case DIAG_CMD_OP_GET_MSG_MASK:
2047 hdlr = diag_cmd_get_msg_mask;
2048 break;
2049 case DIAG_CMD_OP_SET_MSG_MASK:
2050 hdlr = diag_cmd_set_msg_mask;
2051 break;
2052 case DIAG_CMD_OP_SET_ALL_MSG_MASK:
2053 hdlr = diag_cmd_set_all_msg_mask;
2054 break;
2055 }
2056 } else if (*buf == DIAG_CMD_GET_EVENT_MASK) {
2057 hdlr = diag_cmd_get_event_mask;
2058 } else if (*buf == DIAG_CMD_SET_EVENT_MASK) {
2059 hdlr = diag_cmd_update_event_mask;
2060 } else if (*buf == DIAG_CMD_EVENT_TOGGLE) {
2061 hdlr = diag_cmd_toggle_events;
2062 }
2063
2064 if (hdlr)
2065 size = hdlr(buf, len, driver->apps_rsp_buf,
2066 DIAG_MAX_RSP_SIZE, info);
2067
2068 return (size > 0) ? size : 0;
2069}
2070
2071int diag_masks_init(void)
2072{
2073 int err = 0;
2074
2075 err = diag_msg_mask_init();
2076 if (err)
2077 goto fail;
2078
2079 err = diag_build_time_mask_init();
2080 if (err)
2081 goto fail;
2082
2083 err = diag_log_mask_init();
2084 if (err)
2085 goto fail;
2086
2087 err = diag_event_mask_init();
2088 if (err)
2089 goto fail;
2090
2091 if (driver->buf_feature_mask_update == NULL) {
2092 driver->buf_feature_mask_update = kzalloc(sizeof(
2093 struct diag_ctrl_feature_mask) +
2094 FEATURE_MASK_LEN, GFP_KERNEL);
2095 if (driver->buf_feature_mask_update == NULL)
2096 goto fail;
2097 kmemleak_not_leak(driver->buf_feature_mask_update);
2098 }
2099
2100 return 0;
2101fail:
2102 pr_err("diag: Could not initialize diag mask buffers\n");
2103 diag_masks_exit();
2104 return -ENOMEM;
2105}
2106
2107void diag_masks_exit(void)
2108{
2109 diag_msg_mask_exit();
2110 diag_build_time_mask_exit();
2111 diag_log_mask_exit();
2112 diag_event_mask_exit();
2113 kfree(driver->buf_feature_mask_update);
2114}