1 /*
2 * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "qdf_ssr_driver_dump.h"
18 #include "qdf_lock.h"
19 #include "qdf_str.h"
20 #include <qdf_trace.h>
21 #include <qdf_parse.h>
22 #include <qdf_module.h>
23 #include <qdf_util.h>
24 #include <qdf_mem.h>
25 #include <qdf_types.h>
26
27 static qdf_mutex_t region_list_mutex;
28
29 static struct cnss_ssr_driver_dump_entry
30 dump_entry_list[CNSS_HOST_DUMP_TYPE_MAX];
31
32 static size_t num_of_regions_registered;
33
qdf_ssr_driver_dump_init(void)34 QDF_STATUS qdf_ssr_driver_dump_init(void)
35 {
36 QDF_STATUS status;
37
38 status = qdf_mutex_create(®ion_list_mutex);
39 if (QDF_IS_STATUS_ERROR(status))
40 return status;
41
42 num_of_regions_registered = 0;
43 qdf_mem_zero(dump_entry_list, sizeof(dump_entry_list));
44 return status;
45 }
46
qdf_ssr_driver_dump_deinit(void)47 QDF_STATUS qdf_ssr_driver_dump_deinit(void)
48 {
49 QDF_STATUS status;
50
51 status = qdf_mutex_destroy(®ion_list_mutex);
52 if (QDF_IS_STATUS_ERROR(status))
53 return status;
54 if (num_of_regions_registered > 0)
55 qdf_warn("deiniting with regions still registered");
56 num_of_regions_registered = 0;
57 return status;
58 }
59
60 static struct cnss_ssr_driver_dump_entry *
qdf_ssr_driver_dump_find_next_free_entry(void)61 qdf_ssr_driver_dump_find_next_free_entry(void)
62 {
63 int i;
64
65 for (i = 0; i < CNSS_HOST_DUMP_TYPE_MAX; i++) {
66 if (!dump_entry_list[i].buffer_pointer)
67 return &dump_entry_list[i];
68 }
69 return NULL;
70 }
71
72 static struct cnss_ssr_driver_dump_entry *
qdf_ssr_driver_dump_find_entry_by_name(char * region_name)73 qdf_ssr_driver_dump_find_entry_by_name(char *region_name)
74 {
75 int i;
76
77 for (i = 0; i < CNSS_HOST_DUMP_TYPE_MAX; i++) {
78 if (qdf_str_eq(dump_entry_list[i].region_name, region_name) &&
79 dump_entry_list[i].buffer_pointer) {
80 return &dump_entry_list[i];
81 }
82 }
83
84 return NULL;
85 }
86
87 QDF_STATUS
qdf_ssr_driver_dump_register_region(char * region_name,void * region_buffer,size_t region_size)88 qdf_ssr_driver_dump_register_region(char *region_name, void *region_buffer,
89 size_t region_size)
90 {
91 QDF_STATUS status;
92 struct cnss_ssr_driver_dump_entry *entry;
93
94 if (!region_buffer || !region_name) {
95 qdf_err("null region pointer or region_name");
96 return QDF_STATUS_E_NULL_VALUE;
97 }
98
99 status = qdf_mutex_acquire(®ion_list_mutex);
100 if (QDF_IS_STATUS_ERROR(status)) {
101 qdf_err("couldn't acquire lock");
102 return QDF_STATUS_E_RESOURCES;
103 }
104
105 entry = qdf_ssr_driver_dump_find_entry_by_name(region_name);
106 if (entry) {
107 qdf_err("duplicate registration of %s", region_name);
108 status = QDF_STATUS_E_INVAL;
109 goto ret;
110 }
111
112 entry = qdf_ssr_driver_dump_find_next_free_entry();
113 if (!entry) {
114 qdf_err("too many entries: %d, cannot insert %s",
115 num_of_regions_registered, region_name);
116 status = QDF_STATUS_E_NOMEM;
117 goto ret;
118 }
119
120 entry->buffer_pointer = region_buffer;
121 entry->buffer_size = region_size;
122 qdf_str_lcopy(entry->region_name, region_name,
123 sizeof(entry->region_name));
124 num_of_regions_registered++;
125 goto ret;
126
127 ret:
128 if (QDF_IS_STATUS_ERROR(qdf_mutex_release(®ion_list_mutex))) {
129 qdf_err("error releasing lock");
130 return QDF_STATUS_E_RESOURCES;
131 }
132 return status;
133 }
134
qdf_ssr_driver_dump_unregister_region(char * region_name)135 QDF_STATUS qdf_ssr_driver_dump_unregister_region(char *region_name)
136 {
137 QDF_STATUS status;
138 struct cnss_ssr_driver_dump_entry *entry;
139
140 if (!region_name) {
141 qdf_err("null region_name");
142 return QDF_STATUS_E_NULL_VALUE;
143 }
144
145 status = qdf_mutex_acquire(®ion_list_mutex);
146 if (QDF_IS_STATUS_ERROR(status)) {
147 qdf_err("couldn't acquire lock");
148 return QDF_STATUS_E_RESOURCES;
149 }
150
151 entry = qdf_ssr_driver_dump_find_entry_by_name(region_name);
152 if (!entry) {
153 qdf_err("couldn't find entry: %s", region_name);
154 status = QDF_STATUS_E_INVAL;
155 goto ret;
156 }
157
158 entry->buffer_pointer = NULL;
159 num_of_regions_registered--;
160
161 ret:
162 if (QDF_IS_STATUS_ERROR(qdf_mutex_release(®ion_list_mutex))) {
163 qdf_err("error releasing lock");
164 return QDF_STATUS_E_RESOURCES;
165 }
166 return status;
167 }
168
169 QDF_STATUS
qdf_ssr_driver_dump_retrieve_regions(qdf_ssr_driver_dump_entry * input_array,size_t * num_entries_loaded)170 qdf_ssr_driver_dump_retrieve_regions(qdf_ssr_driver_dump_entry
171 *input_array,
172 size_t *num_entries_loaded)
173 {
174 QDF_STATUS status;
175 int i;
176 size_t input_index = 0;
177
178 if (!input_array || !num_entries_loaded) {
179 qdf_err("null input_array or num_entries_loaded");
180 return QDF_STATUS_E_NULL_VALUE;
181 }
182
183 status = qdf_mutex_acquire(®ion_list_mutex);
184 if (QDF_IS_STATUS_ERROR(status)) {
185 qdf_err("couldn't acquire lock");
186 return QDF_STATUS_E_RESOURCES;
187 }
188
189 for (i = 0; i < CNSS_HOST_DUMP_TYPE_MAX; i++) {
190 if (dump_entry_list[i].buffer_pointer) {
191 qdf_mem_copy(&input_array[input_index],
192 &dump_entry_list[i],
193 sizeof(dump_entry_list[i]));
194 input_index++;
195 }
196 }
197 if (input_index != num_of_regions_registered) {
198 qdf_err("num entries mismatch index:%d num reg registered:%d",
199 input_index, num_of_regions_registered);
200 status = QDF_STATUS_E_INVAL;
201 goto ret;
202 }
203 *num_entries_loaded = input_index;
204
205 ret:
206 if (QDF_IS_STATUS_ERROR(qdf_mutex_release(®ion_list_mutex))) {
207 qdf_err("error releasing lock");
208 return QDF_STATUS_E_RESOURCES;
209 }
210 return status;
211 }
212