blob: a8d534289a18509caa36b290744dab8ccd814ee8 [file] [log] [blame]
Ghanim Fodi37b64952017-01-24 15:42:30 +02001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Amir Levy9659e592016-10-27 18:08:27 +03002 *
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/debugfs.h>
14#include "ipahal.h"
15#include "ipahal_i.h"
16#include "ipahal_reg_i.h"
17#include "ipahal_fltrt_i.h"
Skylar Chang2c470a62017-07-25 10:10:44 -070018#include "ipahal_hw_stats_i.h"
19
Amir Levy9659e592016-10-27 18:08:27 +030020
21struct ipahal_context *ipahal_ctx;
22
23static const char *ipahal_imm_cmd_name_to_str[IPA_IMM_CMD_MAX] = {
24 __stringify(IPA_IMM_CMD_IP_V4_FILTER_INIT),
25 __stringify(IPA_IMM_CMD_IP_V6_FILTER_INIT),
26 __stringify(IPA_IMM_CMD_IP_V4_NAT_INIT),
27 __stringify(IPA_IMM_CMD_IP_V4_ROUTING_INIT),
28 __stringify(IPA_IMM_CMD_IP_V6_ROUTING_INIT),
29 __stringify(IPA_IMM_CMD_HDR_INIT_LOCAL),
30 __stringify(IPA_IMM_CMD_HDR_INIT_SYSTEM),
31 __stringify(IPA_IMM_CMD_REGISTER_WRITE),
32 __stringify(IPA_IMM_CMD_NAT_DMA),
33 __stringify(IPA_IMM_CMD_IP_PACKET_INIT),
34 __stringify(IPA_IMM_CMD_DMA_SHARED_MEM),
35 __stringify(IPA_IMM_CMD_IP_PACKET_TAG_STATUS),
36 __stringify(IPA_IMM_CMD_DMA_TASK_32B_ADDR),
Amir Levy05fccd02017-06-13 16:25:45 +030037 __stringify(IPA_IMM_CMD_TABLE_DMA),
Amir Levy9659e592016-10-27 18:08:27 +030038};
39
40static const char *ipahal_pkt_status_exception_to_str
41 [IPAHAL_PKT_STATUS_EXCEPTION_MAX] = {
42 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_NONE),
43 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR),
44 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE),
45 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH),
46 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_PACKET_THRESHOLD),
47 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS),
48 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT),
49 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_NAT),
Amir Levydc65f4c2017-07-06 09:49:50 +030050 __stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT),
Amir Levy9659e592016-10-27 18:08:27 +030051};
52
Michael Adisumartab5d170f2017-05-17 14:34:11 -070053static u16 ipahal_imm_cmd_get_opcode(enum ipahal_imm_cmd_name cmd);
54
Amir Levy9659e592016-10-27 18:08:27 +030055
56static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_dma_task_32b_addr(
57 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
58{
59 struct ipahal_imm_cmd_pyld *pyld;
60 struct ipa_imm_cmd_hw_dma_task_32b_addr *data;
61 struct ipahal_imm_cmd_dma_task_32b_addr *dma_params =
62 (struct ipahal_imm_cmd_dma_task_32b_addr *)params;
63
64 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
65 if (unlikely(!pyld)) {
66 IPAHAL_ERR("kzalloc err\n");
67 return pyld;
68 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -070069 /* Currently supports only one packet */
70 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd) + (1 << 8);
Amir Levy9659e592016-10-27 18:08:27 +030071 pyld->len = sizeof(*data);
72 data = (struct ipa_imm_cmd_hw_dma_task_32b_addr *)pyld->data;
73
74 if (unlikely(dma_params->size1 & ~0xFFFF)) {
75 IPAHAL_ERR("Size1 is bigger than 16bit width 0x%x\n",
76 dma_params->size1);
77 WARN_ON(1);
78 }
79 if (unlikely(dma_params->packet_size & ~0xFFFF)) {
80 IPAHAL_ERR("Pkt size is bigger than 16bit width 0x%x\n",
81 dma_params->packet_size);
82 WARN_ON(1);
83 }
84 data->cmplt = dma_params->cmplt ? 1 : 0;
85 data->eof = dma_params->eof ? 1 : 0;
86 data->flsh = dma_params->flsh ? 1 : 0;
87 data->lock = dma_params->lock ? 1 : 0;
88 data->unlock = dma_params->unlock ? 1 : 0;
89 data->size1 = dma_params->size1;
90 data->addr1 = dma_params->addr1;
91 data->packet_size = dma_params->packet_size;
92
93 return pyld;
94}
95
96static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_packet_tag_status(
97 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
98{
99 struct ipahal_imm_cmd_pyld *pyld;
100 struct ipa_imm_cmd_hw_ip_packet_tag_status *data;
101 struct ipahal_imm_cmd_ip_packet_tag_status *tag_params =
102 (struct ipahal_imm_cmd_ip_packet_tag_status *)params;
103
104 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
105 if (unlikely(!pyld)) {
106 IPAHAL_ERR("kzalloc err\n");
107 return pyld;
108 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700109 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300110 pyld->len = sizeof(*data);
111 data = (struct ipa_imm_cmd_hw_ip_packet_tag_status *)pyld->data;
112
113 if (unlikely(tag_params->tag & ~0xFFFFFFFFFFFF)) {
114 IPAHAL_ERR("tag is bigger than 48bit width 0x%llx\n",
115 tag_params->tag);
116 WARN_ON(1);
117 }
118 data->tag = tag_params->tag;
119
120 return pyld;
121}
122
123static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_dma_shared_mem(
124 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
125{
126 struct ipahal_imm_cmd_pyld *pyld;
127 struct ipa_imm_cmd_hw_dma_shared_mem *data;
128 struct ipahal_imm_cmd_dma_shared_mem *mem_params =
129 (struct ipahal_imm_cmd_dma_shared_mem *)params;
130
131 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
132 if (unlikely(!pyld)) {
133 IPAHAL_ERR("kzalloc err\n");
134 return pyld;
135 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700136 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300137 pyld->len = sizeof(*data);
138 data = (struct ipa_imm_cmd_hw_dma_shared_mem *)pyld->data;
139
140 if (unlikely(mem_params->size & ~0xFFFF)) {
141 IPAHAL_ERR("Size is bigger than 16bit width 0x%x\n",
142 mem_params->size);
143 WARN_ON(1);
144 }
145 if (unlikely(mem_params->local_addr & ~0xFFFF)) {
146 IPAHAL_ERR("Local addr is bigger than 16bit width 0x%x\n",
147 mem_params->local_addr);
148 WARN_ON(1);
149 }
150 data->direction = mem_params->is_read ? 1 : 0;
151 data->size = mem_params->size;
152 data->local_addr = mem_params->local_addr;
153 data->system_addr = mem_params->system_addr;
154 data->skip_pipeline_clear = mem_params->skip_pipeline_clear ? 1 : 0;
155 switch (mem_params->pipeline_clear_options) {
156 case IPAHAL_HPS_CLEAR:
157 data->pipeline_clear_options = 0;
158 break;
159 case IPAHAL_SRC_GRP_CLEAR:
160 data->pipeline_clear_options = 1;
161 break;
162 case IPAHAL_FULL_PIPELINE_CLEAR:
163 data->pipeline_clear_options = 2;
164 break;
165 default:
166 IPAHAL_ERR("unsupported pipline clear option %d\n",
167 mem_params->pipeline_clear_options);
168 WARN_ON(1);
169 };
170
171 return pyld;
172}
173
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700174static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_dma_shared_mem_v_4_0(
175 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
176{
177 struct ipahal_imm_cmd_pyld *pyld;
178 struct ipa_imm_cmd_hw_dma_shared_mem_v_4_0 *data;
179 struct ipahal_imm_cmd_dma_shared_mem *mem_params =
180 (struct ipahal_imm_cmd_dma_shared_mem *)params;
181
182 if (unlikely(mem_params->size & ~0xFFFF)) {
183 IPAHAL_ERR("Size is bigger than 16bit width 0x%x\n",
184 mem_params->size);
185 WARN_ON(1);
186 return NULL;
187 }
188 if (unlikely(mem_params->local_addr & ~0xFFFF)) {
189 IPAHAL_ERR("Local addr is bigger than 16bit width 0x%x\n",
190 mem_params->local_addr);
191 WARN_ON(1);
192 return NULL;
193 }
194
195 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
196 if (unlikely(!pyld)) {
197 WARN_ON(1);
198 return pyld;
199 }
200
201 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
202 pyld->len = sizeof(*data);
203 data = (struct ipa_imm_cmd_hw_dma_shared_mem_v_4_0 *)pyld->data;
204
205 data->direction = mem_params->is_read ? 1 : 0;
206 data->clear_after_read = mem_params->clear_after_read;
207 data->size = mem_params->size;
208 data->local_addr = mem_params->local_addr;
209 data->system_addr = mem_params->system_addr;
210 pyld->opcode |= (mem_params->skip_pipeline_clear ? 1 : 0) << 8;
211 switch (mem_params->pipeline_clear_options) {
212 case IPAHAL_HPS_CLEAR:
213 break;
214 case IPAHAL_SRC_GRP_CLEAR:
215 pyld->opcode |= (1 << 9);
216 break;
217 case IPAHAL_FULL_PIPELINE_CLEAR:
218 pyld->opcode |= (2 << 9);
219 break;
220 default:
221 IPAHAL_ERR("unsupported pipline clear option %d\n",
222 mem_params->pipeline_clear_options);
223 WARN_ON(1);
224 };
225
226 return pyld;
227}
228
Amir Levy9659e592016-10-27 18:08:27 +0300229static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_register_write(
230 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
231{
232 struct ipahal_imm_cmd_pyld *pyld;
233 struct ipa_imm_cmd_hw_register_write *data;
234 struct ipahal_imm_cmd_register_write *regwrt_params =
235 (struct ipahal_imm_cmd_register_write *)params;
236
237 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
238 if (unlikely(!pyld)) {
239 IPAHAL_ERR("kzalloc err\n");
240 return pyld;
241 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700242 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300243 pyld->len = sizeof(*data);
244 data = (struct ipa_imm_cmd_hw_register_write *)pyld->data;
245
246 if (unlikely(regwrt_params->offset & ~0xFFFF)) {
247 IPAHAL_ERR("Offset is bigger than 16bit width 0x%x\n",
248 regwrt_params->offset);
249 WARN_ON(1);
250 }
251 data->offset = regwrt_params->offset;
252 data->value = regwrt_params->value;
253 data->value_mask = regwrt_params->value_mask;
254
255 data->skip_pipeline_clear = regwrt_params->skip_pipeline_clear ? 1 : 0;
256 switch (regwrt_params->pipeline_clear_options) {
257 case IPAHAL_HPS_CLEAR:
258 data->pipeline_clear_options = 0;
259 break;
260 case IPAHAL_SRC_GRP_CLEAR:
261 data->pipeline_clear_options = 1;
262 break;
263 case IPAHAL_FULL_PIPELINE_CLEAR:
264 data->pipeline_clear_options = 2;
265 break;
266 default:
267 IPAHAL_ERR("unsupported pipline clear option %d\n",
268 regwrt_params->pipeline_clear_options);
269 WARN_ON(1);
270 };
271
272 return pyld;
273}
274
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700275static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_register_write_v_4_0(
276 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
277{
278 struct ipahal_imm_cmd_pyld *pyld;
279 struct ipa_imm_cmd_hw_register_write_v_4_0 *data;
280 struct ipahal_imm_cmd_register_write *regwrt_params =
281 (struct ipahal_imm_cmd_register_write *)params;
282
283 if (unlikely(regwrt_params->offset & ~0xFFFF)) {
284 IPAHAL_ERR("Offset is bigger than 16bit width 0x%x\n",
285 regwrt_params->offset);
286 WARN_ON(1);
287 return NULL;
288 }
289
290 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
291 if (unlikely(!pyld)) {
292 WARN_ON(1);
293 return pyld;
294 }
295 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
296 pyld->len = sizeof(*data);
297 data = (struct ipa_imm_cmd_hw_register_write_v_4_0 *)pyld->data;
298
299 data->offset = regwrt_params->offset;
300 data->offset_high = regwrt_params->offset >> 16;
301 data->value = regwrt_params->value;
302 data->value_mask = regwrt_params->value_mask;
303
304 pyld->opcode |= (regwrt_params->skip_pipeline_clear ? 1 : 0) << 8;
305 switch (regwrt_params->pipeline_clear_options) {
306 case IPAHAL_HPS_CLEAR:
307 break;
308 case IPAHAL_SRC_GRP_CLEAR:
309 pyld->opcode |= (1 << 9);
310 break;
311 case IPAHAL_FULL_PIPELINE_CLEAR:
312 pyld->opcode |= (2 << 9);
313 break;
314 default:
315 IPAHAL_ERR("unsupported pipline clear option %d\n",
316 regwrt_params->pipeline_clear_options);
317 WARN_ON(1);
318 };
319
320 return pyld;
321}
322
Amir Levy9659e592016-10-27 18:08:27 +0300323static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_packet_init(
324 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
325{
326 struct ipahal_imm_cmd_pyld *pyld;
327 struct ipa_imm_cmd_hw_ip_packet_init *data;
328 struct ipahal_imm_cmd_ip_packet_init *pktinit_params =
329 (struct ipahal_imm_cmd_ip_packet_init *)params;
330
331 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
332 if (unlikely(!pyld)) {
333 IPAHAL_ERR("kzalloc err\n");
334 return pyld;
335 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700336 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300337 pyld->len = sizeof(*data);
338 data = (struct ipa_imm_cmd_hw_ip_packet_init *)pyld->data;
339
340 if (unlikely(pktinit_params->destination_pipe_index & ~0x1F)) {
341 IPAHAL_ERR("Dst pipe idx is bigger than 5bit width 0x%x\n",
342 pktinit_params->destination_pipe_index);
343 WARN_ON(1);
344 }
345 data->destination_pipe_index = pktinit_params->destination_pipe_index;
346
347 return pyld;
348}
349
350static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_nat_dma(
351 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
352{
353 struct ipahal_imm_cmd_pyld *pyld;
354 struct ipa_imm_cmd_hw_nat_dma *data;
355 struct ipahal_imm_cmd_nat_dma *nat_params =
356 (struct ipahal_imm_cmd_nat_dma *)params;
357
358 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
359 if (unlikely(!pyld)) {
360 IPAHAL_ERR("kzalloc err\n");
361 return pyld;
362 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700363 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300364 pyld->len = sizeof(*data);
365 data = (struct ipa_imm_cmd_hw_nat_dma *)pyld->data;
366
367 data->table_index = nat_params->table_index;
368 data->base_addr = nat_params->base_addr;
369 data->offset = nat_params->offset;
370 data->data = nat_params->data;
371
372 return pyld;
373}
374
Amir Levy05fccd02017-06-13 16:25:45 +0300375static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_table_dma_ipav4(
376 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
377{
378 struct ipahal_imm_cmd_pyld *pyld;
379 struct ipa_imm_cmd_hw_table_dma_ipav4 *data;
380 struct ipahal_imm_cmd_table_dma *nat_params =
381 (struct ipahal_imm_cmd_table_dma *)params;
382
383 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
384 if (unlikely(!pyld)) {
385 IPAHAL_ERR("kzalloc err\n");
386 return pyld;
387 }
388 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
389 pyld->len = sizeof(*data);
390 data = (struct ipa_imm_cmd_hw_table_dma_ipav4 *)pyld->data;
391
392 data->table_index = nat_params->table_index;
393 data->base_addr = nat_params->base_addr;
394 data->offset = nat_params->offset;
395 data->data = nat_params->data;
396
397 return pyld;
398}
399
Amir Levy9659e592016-10-27 18:08:27 +0300400static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_hdr_init_system(
401 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
402{
403 struct ipahal_imm_cmd_pyld *pyld;
404 struct ipa_imm_cmd_hw_hdr_init_system *data;
405 struct ipahal_imm_cmd_hdr_init_system *syshdr_params =
406 (struct ipahal_imm_cmd_hdr_init_system *)params;
407
408 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
409 if (unlikely(!pyld)) {
410 IPAHAL_ERR("kzalloc err\n");
411 return pyld;
412 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700413 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300414 pyld->len = sizeof(*data);
415 data = (struct ipa_imm_cmd_hw_hdr_init_system *)pyld->data;
416
417 data->hdr_table_addr = syshdr_params->hdr_table_addr;
418
419 return pyld;
420}
421
422static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_hdr_init_local(
423 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
424{
425 struct ipahal_imm_cmd_pyld *pyld;
426 struct ipa_imm_cmd_hw_hdr_init_local *data;
427 struct ipahal_imm_cmd_hdr_init_local *lclhdr_params =
428 (struct ipahal_imm_cmd_hdr_init_local *)params;
429
430 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
431 if (unlikely(!pyld)) {
432 IPAHAL_ERR("kzalloc err\n");
433 return pyld;
434 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700435 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300436 pyld->len = sizeof(*data);
437 data = (struct ipa_imm_cmd_hw_hdr_init_local *)pyld->data;
438
439 if (unlikely(lclhdr_params->size_hdr_table & ~0xFFF)) {
440 IPAHAL_ERR("Hdr tble size is bigger than 12bit width 0x%x\n",
441 lclhdr_params->size_hdr_table);
442 WARN_ON(1);
443 }
444 data->hdr_table_addr = lclhdr_params->hdr_table_addr;
445 data->size_hdr_table = lclhdr_params->size_hdr_table;
446 data->hdr_addr = lclhdr_params->hdr_addr;
447
448 return pyld;
449}
450
451static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_v6_routing_init(
452 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
453{
454 struct ipahal_imm_cmd_pyld *pyld;
455 struct ipa_imm_cmd_hw_ip_v6_routing_init *data;
456 struct ipahal_imm_cmd_ip_v6_routing_init *rt6_params =
457 (struct ipahal_imm_cmd_ip_v6_routing_init *)params;
458
459 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
460 if (unlikely(!pyld)) {
461 IPAHAL_ERR("kzalloc err\n");
462 return pyld;
463 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700464 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300465 pyld->len = sizeof(*data);
466 data = (struct ipa_imm_cmd_hw_ip_v6_routing_init *)pyld->data;
467
468 data->hash_rules_addr = rt6_params->hash_rules_addr;
469 data->hash_rules_size = rt6_params->hash_rules_size;
470 data->hash_local_addr = rt6_params->hash_local_addr;
471 data->nhash_rules_addr = rt6_params->nhash_rules_addr;
472 data->nhash_rules_size = rt6_params->nhash_rules_size;
473 data->nhash_local_addr = rt6_params->nhash_local_addr;
474
475 return pyld;
476}
477
478static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_v4_routing_init(
479 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
480{
481 struct ipahal_imm_cmd_pyld *pyld;
482 struct ipa_imm_cmd_hw_ip_v4_routing_init *data;
483 struct ipahal_imm_cmd_ip_v4_routing_init *rt4_params =
484 (struct ipahal_imm_cmd_ip_v4_routing_init *)params;
485
486 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
487 if (unlikely(!pyld)) {
488 IPAHAL_ERR("kzalloc err\n");
489 return pyld;
490 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700491 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300492 pyld->len = sizeof(*data);
493 data = (struct ipa_imm_cmd_hw_ip_v4_routing_init *)pyld->data;
494
495 data->hash_rules_addr = rt4_params->hash_rules_addr;
496 data->hash_rules_size = rt4_params->hash_rules_size;
497 data->hash_local_addr = rt4_params->hash_local_addr;
498 data->nhash_rules_addr = rt4_params->nhash_rules_addr;
499 data->nhash_rules_size = rt4_params->nhash_rules_size;
500 data->nhash_local_addr = rt4_params->nhash_local_addr;
501
502 return pyld;
503}
504
505static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_v4_nat_init(
506 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
507{
508 struct ipahal_imm_cmd_pyld *pyld;
509 struct ipa_imm_cmd_hw_ip_v4_nat_init *data;
510 struct ipahal_imm_cmd_ip_v4_nat_init *nat4_params =
511 (struct ipahal_imm_cmd_ip_v4_nat_init *)params;
512
513 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
514 if (unlikely(!pyld)) {
515 IPAHAL_ERR("kzalloc err\n");
516 return pyld;
517 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700518 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300519 pyld->len = sizeof(*data);
520 data = (struct ipa_imm_cmd_hw_ip_v4_nat_init *)pyld->data;
521
522 data->ipv4_rules_addr = nat4_params->ipv4_rules_addr;
523 data->ipv4_expansion_rules_addr =
524 nat4_params->ipv4_expansion_rules_addr;
525 data->index_table_addr = nat4_params->index_table_addr;
526 data->index_table_expansion_addr =
527 nat4_params->index_table_expansion_addr;
528 data->table_index = nat4_params->table_index;
529 data->ipv4_rules_addr_type =
530 nat4_params->ipv4_rules_addr_shared ? 1 : 0;
531 data->ipv4_expansion_rules_addr_type =
532 nat4_params->ipv4_expansion_rules_addr_shared ? 1 : 0;
533 data->index_table_addr_type =
534 nat4_params->index_table_addr_shared ? 1 : 0;
535 data->index_table_expansion_addr_type =
536 nat4_params->index_table_expansion_addr_shared ? 1 : 0;
537 data->size_base_tables = nat4_params->size_base_tables;
538 data->size_expansion_tables = nat4_params->size_expansion_tables;
539 data->public_ip_addr = nat4_params->public_ip_addr;
540
541 return pyld;
542}
543
544static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_v6_filter_init(
545 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
546{
547 struct ipahal_imm_cmd_pyld *pyld;
548 struct ipa_imm_cmd_hw_ip_v6_filter_init *data;
549 struct ipahal_imm_cmd_ip_v6_filter_init *flt6_params =
550 (struct ipahal_imm_cmd_ip_v6_filter_init *)params;
551
552 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
553 if (unlikely(!pyld)) {
554 IPAHAL_ERR("kzalloc err\n");
555 return pyld;
556 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700557 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300558 pyld->len = sizeof(*data);
559 data = (struct ipa_imm_cmd_hw_ip_v6_filter_init *)pyld->data;
560
561 data->hash_rules_addr = flt6_params->hash_rules_addr;
562 data->hash_rules_size = flt6_params->hash_rules_size;
563 data->hash_local_addr = flt6_params->hash_local_addr;
564 data->nhash_rules_addr = flt6_params->nhash_rules_addr;
565 data->nhash_rules_size = flt6_params->nhash_rules_size;
566 data->nhash_local_addr = flt6_params->nhash_local_addr;
567
568 return pyld;
569}
570
571static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_v4_filter_init(
572 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
573{
574 struct ipahal_imm_cmd_pyld *pyld;
575 struct ipa_imm_cmd_hw_ip_v4_filter_init *data;
576 struct ipahal_imm_cmd_ip_v4_filter_init *flt4_params =
577 (struct ipahal_imm_cmd_ip_v4_filter_init *)params;
578
579 pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
580 if (unlikely(!pyld)) {
581 IPAHAL_ERR("kzalloc err\n");
582 return pyld;
583 }
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700584 pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
Amir Levy9659e592016-10-27 18:08:27 +0300585 pyld->len = sizeof(*data);
586 data = (struct ipa_imm_cmd_hw_ip_v4_filter_init *)pyld->data;
587
588 data->hash_rules_addr = flt4_params->hash_rules_addr;
589 data->hash_rules_size = flt4_params->hash_rules_size;
590 data->hash_local_addr = flt4_params->hash_local_addr;
591 data->nhash_rules_addr = flt4_params->nhash_rules_addr;
592 data->nhash_rules_size = flt4_params->nhash_rules_size;
593 data->nhash_local_addr = flt4_params->nhash_local_addr;
594
595 return pyld;
596}
597
Amir Levy419fb8e2017-09-06 09:23:37 +0300598static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_dummy(
599 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
600{
601 IPAHAL_ERR("no construct function for IMM_CMD=%s, IPA ver %d\n",
602 ipahal_imm_cmd_name_str(cmd), ipahal_ctx->hw_type);
603 WARN_ON(1);
604 return NULL;
605}
606
Amir Levy9659e592016-10-27 18:08:27 +0300607/*
608 * struct ipahal_imm_cmd_obj - immediate command H/W information for
609 * specific IPA version
610 * @construct - CB to construct imm command payload from abstracted structure
611 * @opcode - Immediate command OpCode
Amir Levy9659e592016-10-27 18:08:27 +0300612 */
613struct ipahal_imm_cmd_obj {
614 struct ipahal_imm_cmd_pyld *(*construct)(enum ipahal_imm_cmd_name cmd,
615 const void *params, bool is_atomic_ctx);
616 u16 opcode;
Amir Levy9659e592016-10-27 18:08:27 +0300617};
618
619/*
620 * This table contains the info regard each immediate command for IPAv3
621 * and later.
622 * Information like: opcode and construct functions.
623 * All the information on the IMM on IPAv3 are statically defined below.
624 * If information is missing regard some IMM on some IPA version,
625 * the init function will fill it with the information from the previous
626 * IPA version.
627 * Information is considered missing if all of the fields are 0
628 * If opcode is -1, this means that the IMM is removed on the
629 * specific version
630 */
631static struct ipahal_imm_cmd_obj
632 ipahal_imm_cmd_objs[IPA_HW_MAX][IPA_IMM_CMD_MAX] = {
633 /* IPAv3 */
634 [IPA_HW_v3_0][IPA_IMM_CMD_IP_V4_FILTER_INIT] = {
635 ipa_imm_cmd_construct_ip_v4_filter_init,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700636 3},
Amir Levy9659e592016-10-27 18:08:27 +0300637 [IPA_HW_v3_0][IPA_IMM_CMD_IP_V6_FILTER_INIT] = {
638 ipa_imm_cmd_construct_ip_v6_filter_init,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700639 4},
Amir Levy9659e592016-10-27 18:08:27 +0300640 [IPA_HW_v3_0][IPA_IMM_CMD_IP_V4_NAT_INIT] = {
641 ipa_imm_cmd_construct_ip_v4_nat_init,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700642 5},
Amir Levy9659e592016-10-27 18:08:27 +0300643 [IPA_HW_v3_0][IPA_IMM_CMD_IP_V4_ROUTING_INIT] = {
644 ipa_imm_cmd_construct_ip_v4_routing_init,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700645 7},
Amir Levy9659e592016-10-27 18:08:27 +0300646 [IPA_HW_v3_0][IPA_IMM_CMD_IP_V6_ROUTING_INIT] = {
647 ipa_imm_cmd_construct_ip_v6_routing_init,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700648 8},
Amir Levy9659e592016-10-27 18:08:27 +0300649 [IPA_HW_v3_0][IPA_IMM_CMD_HDR_INIT_LOCAL] = {
650 ipa_imm_cmd_construct_hdr_init_local,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700651 9},
Amir Levy9659e592016-10-27 18:08:27 +0300652 [IPA_HW_v3_0][IPA_IMM_CMD_HDR_INIT_SYSTEM] = {
653 ipa_imm_cmd_construct_hdr_init_system,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700654 10},
Amir Levy9659e592016-10-27 18:08:27 +0300655 [IPA_HW_v3_0][IPA_IMM_CMD_REGISTER_WRITE] = {
656 ipa_imm_cmd_construct_register_write,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700657 12},
Amir Levy9659e592016-10-27 18:08:27 +0300658 [IPA_HW_v3_0][IPA_IMM_CMD_NAT_DMA] = {
659 ipa_imm_cmd_construct_nat_dma,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700660 14},
Amir Levy9659e592016-10-27 18:08:27 +0300661 [IPA_HW_v3_0][IPA_IMM_CMD_IP_PACKET_INIT] = {
662 ipa_imm_cmd_construct_ip_packet_init,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700663 16},
Amir Levy9659e592016-10-27 18:08:27 +0300664 [IPA_HW_v3_0][IPA_IMM_CMD_DMA_TASK_32B_ADDR] = {
665 ipa_imm_cmd_construct_dma_task_32b_addr,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700666 17},
Amir Levy9659e592016-10-27 18:08:27 +0300667 [IPA_HW_v3_0][IPA_IMM_CMD_DMA_SHARED_MEM] = {
668 ipa_imm_cmd_construct_dma_shared_mem,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700669 19},
Amir Levy9659e592016-10-27 18:08:27 +0300670 [IPA_HW_v3_0][IPA_IMM_CMD_IP_PACKET_TAG_STATUS] = {
671 ipa_imm_cmd_construct_ip_packet_tag_status,
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700672 20},
673
674 /* IPAv4 */
675 [IPA_HW_v4_0][IPA_IMM_CMD_REGISTER_WRITE] = {
676 ipa_imm_cmd_construct_register_write_v_4_0,
677 12},
Amir Levy05fccd02017-06-13 16:25:45 +0300678 /* NAT_DMA was renamed to TABLE_DMA for IPAv4 */
679 [IPA_HW_v4_0][IPA_IMM_CMD_NAT_DMA] = {
Amir Levy419fb8e2017-09-06 09:23:37 +0300680 ipa_imm_cmd_construct_dummy,
681 -1},
Amir Levy05fccd02017-06-13 16:25:45 +0300682 [IPA_HW_v4_0][IPA_IMM_CMD_TABLE_DMA] = {
683 ipa_imm_cmd_construct_table_dma_ipav4,
684 14},
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700685 [IPA_HW_v4_0][IPA_IMM_CMD_DMA_SHARED_MEM] = {
686 ipa_imm_cmd_construct_dma_shared_mem_v_4_0,
687 19},
Amir Levy9659e592016-10-27 18:08:27 +0300688};
689
690/*
691 * ipahal_imm_cmd_init() - Build the Immediate command information table
692 * See ipahal_imm_cmd_objs[][] comments
693 */
694static int ipahal_imm_cmd_init(enum ipa_hw_type ipa_hw_type)
695{
696 int i;
697 int j;
698 struct ipahal_imm_cmd_obj zero_obj;
699
700 IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
701
702 if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
703 IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
704 return -EINVAL;
705 }
706
707 memset(&zero_obj, 0, sizeof(zero_obj));
708 for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
709 for (j = 0; j < IPA_IMM_CMD_MAX ; j++) {
710 if (!memcmp(&ipahal_imm_cmd_objs[i+1][j], &zero_obj,
711 sizeof(struct ipahal_imm_cmd_obj))) {
712 memcpy(&ipahal_imm_cmd_objs[i+1][j],
713 &ipahal_imm_cmd_objs[i][j],
714 sizeof(struct ipahal_imm_cmd_obj));
715 } else {
716 /*
717 * explicitly overridden immediate command.
718 * Check validity
719 */
720 if (!ipahal_imm_cmd_objs[i+1][j].opcode) {
721 IPAHAL_ERR(
722 "imm_cmd=%s with zero opcode ipa_ver=%d\n",
723 ipahal_imm_cmd_name_str(j), i+1);
724 WARN_ON(1);
725 }
726 if (!ipahal_imm_cmd_objs[i+1][j].construct) {
727 IPAHAL_ERR(
728 "imm_cmd=%s with NULL construct func ipa_ver=%d\n",
729 ipahal_imm_cmd_name_str(j), i+1);
730 WARN_ON(1);
731 }
732 }
733 }
734 }
735
736 return 0;
737}
738
739/*
740 * ipahal_imm_cmd_name_str() - returns string that represent the imm cmd
741 * @cmd_name: [in] Immediate command name
742 */
743const char *ipahal_imm_cmd_name_str(enum ipahal_imm_cmd_name cmd_name)
744{
745 if (cmd_name < 0 || cmd_name >= IPA_IMM_CMD_MAX) {
746 IPAHAL_ERR("requested name of invalid imm_cmd=%d\n", cmd_name);
747 return "Invalid IMM_CMD";
748 }
749
750 return ipahal_imm_cmd_name_to_str[cmd_name];
751}
752
753/*
754 * ipahal_imm_cmd_get_opcode() - Get the fixed opcode of the immediate command
755 */
Michael Adisumartab5d170f2017-05-17 14:34:11 -0700756static u16 ipahal_imm_cmd_get_opcode(enum ipahal_imm_cmd_name cmd)
Amir Levy9659e592016-10-27 18:08:27 +0300757{
758 u32 opcode;
759
760 if (cmd >= IPA_IMM_CMD_MAX) {
761 IPAHAL_ERR("Invalid immediate command imm_cmd=%u\n", cmd);
762 ipa_assert();
763 return -EFAULT;
764 }
765
766 IPAHAL_DBG_LOW("Get opcode of IMM_CMD=%s\n",
767 ipahal_imm_cmd_name_str(cmd));
768 opcode = ipahal_imm_cmd_objs[ipahal_ctx->hw_type][cmd].opcode;
769 if (opcode == -1) {
770 IPAHAL_ERR("Try to get opcode of obsolete IMM_CMD=%s\n",
771 ipahal_imm_cmd_name_str(cmd));
772 ipa_assert();
773 return -EFAULT;
774 }
775
776 return opcode;
777}
778
779/*
Amir Levy9659e592016-10-27 18:08:27 +0300780 * ipahal_construct_imm_cmd() - Construct immdiate command
781 * This function builds imm cmd bulk that can be be sent to IPA
782 * The command will be allocated dynamically.
783 * After done using it, call ipahal_destroy_imm_cmd() to release it
784 */
785struct ipahal_imm_cmd_pyld *ipahal_construct_imm_cmd(
786 enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
787{
788 if (!params) {
789 IPAHAL_ERR("Input error: params=%p\n", params);
790 ipa_assert();
791 return NULL;
792 }
793
794 if (cmd >= IPA_IMM_CMD_MAX) {
795 IPAHAL_ERR("Invalid immediate command %u\n", cmd);
796 ipa_assert();
797 return NULL;
798 }
799
800 IPAHAL_DBG_LOW("construct IMM_CMD:%s\n", ipahal_imm_cmd_name_str(cmd));
801 return ipahal_imm_cmd_objs[ipahal_ctx->hw_type][cmd].construct(
802 cmd, params, is_atomic_ctx);
803}
804
805/*
806 * ipahal_construct_nop_imm_cmd() - Construct immediate comamnd for NO-Op
807 * Core driver may want functionality to inject NOP commands to IPA
808 * to ensure e.g., PIPLINE clear before someother operation.
809 * The functionality given by this function can be reached by
810 * ipahal_construct_imm_cmd(). This function is helper to the core driver
811 * to reach this NOP functionlity easily.
812 * @skip_pipline_clear: if to skip pipeline clear waiting (don't wait)
813 * @pipline_clr_opt: options for pipeline clear waiting
814 * @is_atomic_ctx: is called in atomic context or can sleep?
815 */
816struct ipahal_imm_cmd_pyld *ipahal_construct_nop_imm_cmd(
817 bool skip_pipline_clear,
818 enum ipahal_pipeline_clear_option pipline_clr_opt,
819 bool is_atomic_ctx)
820{
821 struct ipahal_imm_cmd_register_write cmd;
822 struct ipahal_imm_cmd_pyld *cmd_pyld;
823
824 memset(&cmd, 0, sizeof(cmd));
825 cmd.skip_pipeline_clear = skip_pipline_clear;
826 cmd.pipeline_clear_options = pipline_clr_opt;
827 cmd.value_mask = 0x0;
828
829 cmd_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_REGISTER_WRITE,
830 &cmd, is_atomic_ctx);
831
832 if (!cmd_pyld)
833 IPAHAL_ERR("failed to construct register_write imm cmd\n");
834
835 return cmd_pyld;
836}
837
838
839/* IPA Packet Status Logic */
840
841#define IPA_PKT_STATUS_SET_MSK(__hw_bit_msk, __shft) \
842 (status->status_mask |= \
843 ((hw_status->status_mask & (__hw_bit_msk) ? 1 : 0) << (__shft)))
844
845static void ipa_pkt_status_parse(
846 const void *unparsed_status, struct ipahal_pkt_status *status)
847{
848 enum ipahal_pkt_status_opcode opcode = 0;
849 enum ipahal_pkt_status_exception exception_type = 0;
Amir Levydc65f4c2017-07-06 09:49:50 +0300850 bool is_ipv6;
Amir Levy9659e592016-10-27 18:08:27 +0300851
852 struct ipa_pkt_status_hw *hw_status =
853 (struct ipa_pkt_status_hw *)unparsed_status;
854
Amir Levydc65f4c2017-07-06 09:49:50 +0300855 is_ipv6 = (hw_status->status_mask & 0x80) ? false : true;
856
Amir Levy9659e592016-10-27 18:08:27 +0300857 status->pkt_len = hw_status->pkt_len;
858 status->endp_src_idx = hw_status->endp_src_idx;
859 status->endp_dest_idx = hw_status->endp_dest_idx;
860 status->metadata = hw_status->metadata;
861 status->flt_local = hw_status->flt_local;
862 status->flt_hash = hw_status->flt_hash;
863 status->flt_global = hw_status->flt_hash;
864 status->flt_ret_hdr = hw_status->flt_ret_hdr;
865 status->flt_miss = ~(hw_status->flt_rule_id) ? false : true;
866 status->flt_rule_id = hw_status->flt_rule_id;
867 status->rt_local = hw_status->rt_local;
868 status->rt_hash = hw_status->rt_hash;
869 status->ucp = hw_status->ucp;
870 status->rt_tbl_idx = hw_status->rt_tbl_idx;
871 status->rt_miss = ~(hw_status->rt_rule_id) ? false : true;
872 status->rt_rule_id = hw_status->rt_rule_id;
873 status->nat_hit = hw_status->nat_hit;
874 status->nat_entry_idx = hw_status->nat_entry_idx;
875 status->tag_info = hw_status->tag_info;
876 status->seq_num = hw_status->seq_num;
877 status->time_of_day_ctr = hw_status->time_of_day_ctr;
878 status->hdr_local = hw_status->hdr_local;
879 status->hdr_offset = hw_status->hdr_offset;
880 status->frag_hit = hw_status->frag_hit;
881 status->frag_rule = hw_status->frag_rule;
882
883 switch (hw_status->status_opcode) {
884 case 0x1:
885 opcode = IPAHAL_PKT_STATUS_OPCODE_PACKET;
886 break;
887 case 0x2:
888 opcode = IPAHAL_PKT_STATUS_OPCODE_NEW_FRAG_RULE;
889 break;
890 case 0x4:
891 opcode = IPAHAL_PKT_STATUS_OPCODE_DROPPED_PACKET;
892 break;
893 case 0x8:
894 opcode = IPAHAL_PKT_STATUS_OPCODE_SUSPENDED_PACKET;
895 break;
896 case 0x10:
897 opcode = IPAHAL_PKT_STATUS_OPCODE_LOG;
898 break;
899 case 0x20:
900 opcode = IPAHAL_PKT_STATUS_OPCODE_DCMP;
901 break;
902 case 0x40:
903 opcode = IPAHAL_PKT_STATUS_OPCODE_PACKET_2ND_PASS;
904 break;
905 default:
906 IPAHAL_ERR("unsupported Status Opcode 0x%x\n",
907 hw_status->status_opcode);
908 WARN_ON(1);
909 };
910 status->status_opcode = opcode;
911
912 switch (hw_status->nat_type) {
913 case 0:
914 status->nat_type = IPAHAL_PKT_STATUS_NAT_NONE;
915 break;
916 case 1:
917 status->nat_type = IPAHAL_PKT_STATUS_NAT_SRC;
918 break;
919 case 2:
920 status->nat_type = IPAHAL_PKT_STATUS_NAT_DST;
921 break;
922 default:
923 IPAHAL_ERR("unsupported Status NAT type 0x%x\n",
924 hw_status->nat_type);
925 WARN_ON(1);
926 };
927
928 switch (hw_status->exception) {
929 case 0:
930 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NONE;
931 break;
932 case 1:
933 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_DEAGGR;
934 break;
935 case 4:
936 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPTYPE;
937 break;
938 case 8:
939 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_PACKET_LENGTH;
940 break;
941 case 16:
942 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS;
943 break;
944 case 32:
945 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT;
946 break;
947 case 64:
Amir Levydc65f4c2017-07-06 09:49:50 +0300948 if (is_ipv6)
949 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT;
950 else
951 exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
Amir Levy9659e592016-10-27 18:08:27 +0300952 break;
953 default:
954 IPAHAL_ERR("unsupported Status Exception type 0x%x\n",
955 hw_status->exception);
956 WARN_ON(1);
957 };
958 status->exception = exception_type;
959
960 IPA_PKT_STATUS_SET_MSK(0x1, IPAHAL_PKT_STATUS_MASK_FRAG_PROCESS_SHFT);
961 IPA_PKT_STATUS_SET_MSK(0x2, IPAHAL_PKT_STATUS_MASK_FILT_PROCESS_SHFT);
962 IPA_PKT_STATUS_SET_MSK(0x4, IPAHAL_PKT_STATUS_MASK_NAT_PROCESS_SHFT);
963 IPA_PKT_STATUS_SET_MSK(0x8, IPAHAL_PKT_STATUS_MASK_ROUTE_PROCESS_SHFT);
964 IPA_PKT_STATUS_SET_MSK(0x10, IPAHAL_PKT_STATUS_MASK_TAG_VALID_SHFT);
965 IPA_PKT_STATUS_SET_MSK(0x20, IPAHAL_PKT_STATUS_MASK_FRAGMENT_SHFT);
966 IPA_PKT_STATUS_SET_MSK(0x40,
967 IPAHAL_PKT_STATUS_MASK_FIRST_FRAGMENT_SHFT);
968 IPA_PKT_STATUS_SET_MSK(0x80, IPAHAL_PKT_STATUS_MASK_V4_SHFT);
969 IPA_PKT_STATUS_SET_MSK(0x100,
970 IPAHAL_PKT_STATUS_MASK_CKSUM_PROCESS_SHFT);
971 IPA_PKT_STATUS_SET_MSK(0x200, IPAHAL_PKT_STATUS_MASK_AGGR_PROCESS_SHFT);
972 IPA_PKT_STATUS_SET_MSK(0x400, IPAHAL_PKT_STATUS_MASK_DEST_EOT_SHFT);
973 IPA_PKT_STATUS_SET_MSK(0x800,
974 IPAHAL_PKT_STATUS_MASK_DEAGGR_PROCESS_SHFT);
975 IPA_PKT_STATUS_SET_MSK(0x1000, IPAHAL_PKT_STATUS_MASK_DEAGG_FIRST_SHFT);
976 IPA_PKT_STATUS_SET_MSK(0x2000, IPAHAL_PKT_STATUS_MASK_SRC_EOT_SHFT);
977 IPA_PKT_STATUS_SET_MSK(0x4000, IPAHAL_PKT_STATUS_MASK_PREV_EOT_SHFT);
978 IPA_PKT_STATUS_SET_MSK(0x8000, IPAHAL_PKT_STATUS_MASK_BYTE_LIMIT_SHFT);
979 status->status_mask &= 0xFFFF;
980}
981
982/*
983 * struct ipahal_pkt_status_obj - Pakcet Status H/W information for
984 * specific IPA version
985 * @size: H/W size of the status packet
986 * @parse: CB that parses the H/W packet status into the abstracted structure
987 */
988struct ipahal_pkt_status_obj {
989 u32 size;
990 void (*parse)(const void *unparsed_status,
991 struct ipahal_pkt_status *status);
992};
993
994/*
995 * This table contains the info regard packet status for IPAv3 and later
996 * Information like: size of packet status and parsing function
997 * All the information on the pkt Status on IPAv3 are statically defined below.
998 * If information is missing regard some IPA version, the init function
999 * will fill it with the information from the previous IPA version.
1000 * Information is considered missing if all of the fields are 0
1001 */
1002static struct ipahal_pkt_status_obj ipahal_pkt_status_objs[IPA_HW_MAX] = {
1003 /* IPAv3 */
1004 [IPA_HW_v3_0] = {
1005 IPA3_0_PKT_STATUS_SIZE,
1006 ipa_pkt_status_parse,
1007 },
1008};
1009
1010/*
1011 * ipahal_pkt_status_init() - Build the packet status information array
1012 * for the different IPA versions
1013 * See ipahal_pkt_status_objs[] comments
1014 */
1015static int ipahal_pkt_status_init(enum ipa_hw_type ipa_hw_type)
1016{
1017 int i;
1018 struct ipahal_pkt_status_obj zero_obj;
1019
1020 IPAHAL_DBG_LOW("Entry - HW_TYPE=%d\n", ipa_hw_type);
1021
1022 if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
1023 IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
1024 return -EINVAL;
1025 }
1026
1027 /*
1028 * Since structure alignment is implementation dependent,
1029 * add test to avoid different and incompatible data layouts.
1030 *
1031 * In case new H/W has different size or structure of status packet,
1032 * add a compile time validty check for it like below (as well as
1033 * the new defines and/or the new strucutre in the internal header).
1034 */
1035 BUILD_BUG_ON(sizeof(struct ipa_pkt_status_hw) !=
1036 IPA3_0_PKT_STATUS_SIZE);
1037
1038 memset(&zero_obj, 0, sizeof(zero_obj));
1039 for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; i++) {
1040 if (!memcmp(&ipahal_pkt_status_objs[i+1], &zero_obj,
1041 sizeof(struct ipahal_pkt_status_obj))) {
1042 memcpy(&ipahal_pkt_status_objs[i+1],
1043 &ipahal_pkt_status_objs[i],
1044 sizeof(struct ipahal_pkt_status_obj));
1045 } else {
1046 /*
1047 * explicitly overridden Packet Status info
1048 * Check validity
1049 */
1050 if (!ipahal_pkt_status_objs[i+1].size) {
1051 IPAHAL_ERR(
1052 "Packet Status with zero size ipa_ver=%d\n",
1053 i+1);
1054 WARN_ON(1);
1055 }
1056 if (!ipahal_pkt_status_objs[i+1].parse) {
1057 IPAHAL_ERR(
1058 "Packet Status without Parse func ipa_ver=%d\n",
1059 i+1);
1060 WARN_ON(1);
1061 }
1062 }
1063 }
1064
1065 return 0;
1066}
1067
1068/*
1069 * ipahal_pkt_status_get_size() - Get H/W size of packet status
1070 */
1071u32 ipahal_pkt_status_get_size(void)
1072{
1073 return ipahal_pkt_status_objs[ipahal_ctx->hw_type].size;
1074}
1075
1076/*
1077 * ipahal_pkt_status_parse() - Parse Packet Status payload to abstracted form
1078 * @unparsed_status: Pointer to H/W format of the packet status as read from H/W
1079 * @status: Pointer to pre-allocated buffer where the parsed info will be stored
1080 */
1081void ipahal_pkt_status_parse(const void *unparsed_status,
1082 struct ipahal_pkt_status *status)
1083{
1084 if (!unparsed_status || !status) {
1085 IPAHAL_ERR("Input Error: unparsed_status=%p status=%p\n",
1086 unparsed_status, status);
1087 return;
1088 }
1089
1090 IPAHAL_DBG_LOW("Parse Status Packet\n");
1091 memset(status, 0, sizeof(*status));
1092 ipahal_pkt_status_objs[ipahal_ctx->hw_type].parse(unparsed_status,
1093 status);
1094}
1095
1096/*
1097 * ipahal_pkt_status_exception_str() - returns string represents exception type
1098 * @exception: [in] The exception type
1099 */
1100const char *ipahal_pkt_status_exception_str(
1101 enum ipahal_pkt_status_exception exception)
1102{
1103 if (exception < 0 || exception >= IPAHAL_PKT_STATUS_EXCEPTION_MAX) {
1104 IPAHAL_ERR(
1105 "requested string of invalid pkt_status exception=%d\n",
1106 exception);
1107 return "Invalid PKT_STATUS_EXCEPTION";
1108 }
1109
1110 return ipahal_pkt_status_exception_to_str[exception];
1111}
1112
1113#ifdef CONFIG_DEBUG_FS
1114static void ipahal_debugfs_init(void)
1115{
1116 ipahal_ctx->dent = debugfs_create_dir("ipahal", 0);
1117 if (!ipahal_ctx->dent || IS_ERR(ipahal_ctx->dent)) {
1118 IPAHAL_ERR("fail to create ipahal debugfs folder\n");
1119 goto fail;
1120 }
1121
1122 return;
1123fail:
1124 debugfs_remove_recursive(ipahal_ctx->dent);
1125 ipahal_ctx->dent = NULL;
1126}
1127
1128static void ipahal_debugfs_remove(void)
1129{
1130 if (!ipahal_ctx)
1131 return;
1132
1133 if (IS_ERR(ipahal_ctx->dent)) {
1134 IPAHAL_ERR("ipahal debugfs folder was not created\n");
1135 return;
1136 }
1137
1138 debugfs_remove_recursive(ipahal_ctx->dent);
1139}
1140#else /* CONFIG_DEBUG_FS */
1141static void ipahal_debugfs_init(void) {}
1142static void ipahal_debugfs_remove(void) {}
1143#endif /* CONFIG_DEBUG_FS */
1144
1145/*
1146 * ipahal_cp_hdr_to_hw_buff_v3() - copy header to hardware buffer according to
1147 * base address and offset given.
1148 * @base: dma base address
1149 * @offset: offset from base address where the data will be copied
1150 * @hdr: the header to be copied
1151 * @hdr_len: the length of the header
1152 */
1153static void ipahal_cp_hdr_to_hw_buff_v3(void *const base, u32 offset,
1154 u8 *const hdr, u32 hdr_len)
1155{
1156 memcpy(base + offset, hdr, hdr_len);
1157}
1158
1159/*
1160 * ipahal_cp_proc_ctx_to_hw_buff_v3() - copy processing context to
1161 * base address and offset given.
1162 * @type: header processing context type (no processing context,
1163 * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
1164 * @base: dma base address
1165 * @offset: offset from base address where the data will be copied
1166 * @hdr_len: the length of the header
1167 * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
1168 * @phys_base: memory location in DDR
1169 * @hdr_base_addr: base address in table
1170 * @offset_entry: offset from hdr_base_addr in table
Skylar Chang7fa22712017-04-03 18:29:21 -07001171 * @l2tp_params: l2tp parameters
Amir Levy9659e592016-10-27 18:08:27 +03001172 */
1173static int ipahal_cp_proc_ctx_to_hw_buff_v3(enum ipa_hdr_proc_type type,
1174 void *const base, u32 offset,
1175 u32 hdr_len, bool is_hdr_proc_ctx,
1176 dma_addr_t phys_base, u32 hdr_base_addr,
Skylar Chang7fa22712017-04-03 18:29:21 -07001177 struct ipa_hdr_offset_entry *offset_entry,
Shihuan Liufe2818b2017-07-03 22:14:55 -07001178 struct ipa_l2tp_hdr_proc_ctx_params l2tp_params){
Amir Levy9659e592016-10-27 18:08:27 +03001179 if (type == IPA_HDR_PROC_NONE) {
1180 struct ipa_hw_hdr_proc_ctx_add_hdr_seq *ctx;
1181
1182 ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_seq *)
1183 (base + offset);
1184 ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
1185 ctx->hdr_add.tlv.length = 1;
1186 ctx->hdr_add.tlv.value = hdr_len;
1187 ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
1188 hdr_base_addr + offset_entry->offset;
1189 IPAHAL_DBG("header address 0x%x\n",
1190 ctx->hdr_add.hdr_addr);
1191 ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
1192 ctx->end.length = 0;
1193 ctx->end.value = 0;
Skylar Chang7fa22712017-04-03 18:29:21 -07001194 } else if (type == IPA_HDR_PROC_L2TP_HEADER_ADD) {
1195 struct ipa_hw_hdr_proc_ctx_add_l2tp_hdr_cmd_seq *ctx;
1196
1197 ctx = (struct ipa_hw_hdr_proc_ctx_add_l2tp_hdr_cmd_seq *)
1198 (base + offset);
1199 ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
1200 ctx->hdr_add.tlv.length = 1;
1201 ctx->hdr_add.tlv.value = hdr_len;
1202 ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
1203 hdr_base_addr + offset_entry->offset;
1204 IPAHAL_DBG("header address 0x%x\n",
1205 ctx->hdr_add.hdr_addr);
1206 ctx->l2tp_params.tlv.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
1207 ctx->l2tp_params.tlv.length = 1;
1208 ctx->l2tp_params.tlv.value =
1209 IPA_HDR_UCP_L2TP_HEADER_ADD;
1210 ctx->l2tp_params.l2tp_params.eth_hdr_retained =
1211 l2tp_params.hdr_add_param.eth_hdr_retained;
1212 ctx->l2tp_params.l2tp_params.input_ip_version =
1213 l2tp_params.hdr_add_param.input_ip_version;
1214 ctx->l2tp_params.l2tp_params.output_ip_version =
1215 l2tp_params.hdr_add_param.output_ip_version;
1216
1217 IPAHAL_DBG("command id %d\n", ctx->l2tp_params.tlv.value);
1218 ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
1219 ctx->end.length = 0;
1220 ctx->end.value = 0;
1221 } else if (type == IPA_HDR_PROC_L2TP_HEADER_REMOVE) {
1222 struct ipa_hw_hdr_proc_ctx_remove_l2tp_hdr_cmd_seq *ctx;
1223
1224 ctx = (struct ipa_hw_hdr_proc_ctx_remove_l2tp_hdr_cmd_seq *)
1225 (base + offset);
1226 ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
1227 ctx->hdr_add.tlv.length = 1;
1228 ctx->hdr_add.tlv.value = hdr_len;
1229 ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
1230 hdr_base_addr + offset_entry->offset;
1231 IPAHAL_DBG("header address 0x%x length %d\n",
1232 ctx->hdr_add.hdr_addr, ctx->hdr_add.tlv.value);
1233 ctx->l2tp_params.tlv.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
1234 ctx->l2tp_params.tlv.length = 1;
1235 ctx->l2tp_params.tlv.value =
1236 IPA_HDR_UCP_L2TP_HEADER_REMOVE;
1237 ctx->l2tp_params.l2tp_params.hdr_len_remove =
1238 l2tp_params.hdr_remove_param.hdr_len_remove;
1239 ctx->l2tp_params.l2tp_params.eth_hdr_retained =
1240 l2tp_params.hdr_remove_param.eth_hdr_retained;
Shihuan Liufe2818b2017-07-03 22:14:55 -07001241 ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size_valid =
1242 l2tp_params.hdr_remove_param.hdr_ofst_pkt_size_valid;
1243 ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size =
1244 l2tp_params.hdr_remove_param.hdr_ofst_pkt_size;
1245 ctx->l2tp_params.l2tp_params.hdr_endianness =
1246 l2tp_params.hdr_remove_param.hdr_endianness;
1247 IPAHAL_DBG("hdr ofst valid: %d, hdr ofst pkt size: %d\n",
1248 ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size_valid,
1249 ctx->l2tp_params.l2tp_params.hdr_ofst_pkt_size);
1250 IPAHAL_DBG("endianness: %d\n",
1251 ctx->l2tp_params.l2tp_params.hdr_endianness);
Skylar Chang7fa22712017-04-03 18:29:21 -07001252
1253 IPAHAL_DBG("command id %d\n", ctx->l2tp_params.tlv.value);
1254 ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
1255 ctx->end.length = 0;
1256 ctx->end.value = 0;
Amir Levy9659e592016-10-27 18:08:27 +03001257 } else {
1258 struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *ctx;
1259
1260 ctx = (struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq *)
1261 (base + offset);
1262 ctx->hdr_add.tlv.type = IPA_PROC_CTX_TLV_TYPE_HDR_ADD;
1263 ctx->hdr_add.tlv.length = 1;
1264 ctx->hdr_add.tlv.value = hdr_len;
1265 ctx->hdr_add.hdr_addr = is_hdr_proc_ctx ? phys_base :
1266 hdr_base_addr + offset_entry->offset;
1267 IPAHAL_DBG("header address 0x%x\n",
1268 ctx->hdr_add.hdr_addr);
1269 ctx->cmd.type = IPA_PROC_CTX_TLV_TYPE_PROC_CMD;
1270 ctx->cmd.length = 0;
1271 switch (type) {
1272 case IPA_HDR_PROC_ETHII_TO_ETHII:
1273 ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_ETHII;
1274 break;
1275 case IPA_HDR_PROC_ETHII_TO_802_3:
1276 ctx->cmd.value = IPA_HDR_UCP_ETHII_TO_802_3;
1277 break;
1278 case IPA_HDR_PROC_802_3_TO_ETHII:
1279 ctx->cmd.value = IPA_HDR_UCP_802_3_TO_ETHII;
1280 break;
1281 case IPA_HDR_PROC_802_3_TO_802_3:
1282 ctx->cmd.value = IPA_HDR_UCP_802_3_TO_802_3;
1283 break;
1284 default:
1285 IPAHAL_ERR("unknown ipa_hdr_proc_type %d", type);
1286 WARN_ON(1);
1287 return -EINVAL;
1288 }
1289 IPAHAL_DBG("command id %d\n", ctx->cmd.value);
1290 ctx->end.type = IPA_PROC_CTX_TLV_TYPE_END;
1291 ctx->end.length = 0;
1292 ctx->end.value = 0;
1293 }
1294
1295 return 0;
1296}
1297
1298/*
1299 * ipahal_get_proc_ctx_needed_len_v3() - calculates the needed length for
1300 * addition of header processing context according to the type of processing
1301 * context.
1302 * @type: header processing context type (no processing context,
1303 * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
1304 */
1305static int ipahal_get_proc_ctx_needed_len_v3(enum ipa_hdr_proc_type type)
1306{
1307 return (type == IPA_HDR_PROC_NONE) ?
1308 sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_seq) :
1309 sizeof(struct ipa_hw_hdr_proc_ctx_add_hdr_cmd_seq);
1310}
1311
1312/*
1313 * struct ipahal_hdr_funcs - headers handling functions for specific IPA
1314 * version
1315 * @ipahal_cp_hdr_to_hw_buff - copy function for regular headers
1316 */
1317struct ipahal_hdr_funcs {
1318 void (*ipahal_cp_hdr_to_hw_buff)(void *const base, u32 offset,
1319 u8 *const hdr, u32 hdr_len);
1320
1321 int (*ipahal_cp_proc_ctx_to_hw_buff)(enum ipa_hdr_proc_type type,
1322 void *const base, u32 offset, u32 hdr_len,
1323 bool is_hdr_proc_ctx, dma_addr_t phys_base,
1324 u32 hdr_base_addr,
Skylar Chang7fa22712017-04-03 18:29:21 -07001325 struct ipa_hdr_offset_entry *offset_entry,
Shihuan Liufe2818b2017-07-03 22:14:55 -07001326 struct ipa_l2tp_hdr_proc_ctx_params l2tp_params);
Amir Levy9659e592016-10-27 18:08:27 +03001327
1328 int (*ipahal_get_proc_ctx_needed_len)(enum ipa_hdr_proc_type type);
1329};
1330
1331static struct ipahal_hdr_funcs hdr_funcs;
1332
1333static void ipahal_hdr_init(enum ipa_hw_type ipa_hw_type)
1334{
1335
1336 IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
1337
1338 /*
1339 * once there are changes in HW and need to use different case, insert
1340 * new case for the new h/w. put the default always for the latest HW
1341 * and make sure all previous supported versions have their cases.
1342 */
1343 switch (ipa_hw_type) {
1344 case IPA_HW_v3_0:
1345 default:
1346 hdr_funcs.ipahal_cp_hdr_to_hw_buff =
1347 ipahal_cp_hdr_to_hw_buff_v3;
1348 hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff =
1349 ipahal_cp_proc_ctx_to_hw_buff_v3;
1350 hdr_funcs.ipahal_get_proc_ctx_needed_len =
1351 ipahal_get_proc_ctx_needed_len_v3;
1352 }
1353 IPAHAL_DBG("Exit\n");
1354}
1355
1356/*
1357 * ipahal_cp_hdr_to_hw_buff() - copy header to hardware buffer according to
1358 * base address and offset given.
1359 * @base: dma base address
1360 * @offset: offset from base address where the data will be copied
1361 * @hdr: the header to be copied
1362 * @hdr_len: the length of the header
1363 */
1364void ipahal_cp_hdr_to_hw_buff(void *base, u32 offset, u8 *const hdr,
1365 u32 hdr_len)
1366{
1367 IPAHAL_DBG_LOW("Entry\n");
1368 IPAHAL_DBG("base %p, offset %d, hdr %p, hdr_len %d\n", base,
1369 offset, hdr, hdr_len);
1370 if (!base || !hdr_len || !hdr) {
1371 IPAHAL_ERR("failed on validating params");
1372 return;
1373 }
1374
1375 hdr_funcs.ipahal_cp_hdr_to_hw_buff(base, offset, hdr, hdr_len);
1376
1377 IPAHAL_DBG_LOW("Exit\n");
1378}
1379
1380/*
1381 * ipahal_cp_proc_ctx_to_hw_buff() - copy processing context to
1382 * base address and offset given.
1383 * @type: type of header processing context
1384 * @base: dma base address
1385 * @offset: offset from base address where the data will be copied
1386 * @hdr_len: the length of the header
1387 * @is_hdr_proc_ctx: header is located in phys_base (true) or hdr_base_addr
1388 * @phys_base: memory location in DDR
1389 * @hdr_base_addr: base address in table
1390 * @offset_entry: offset from hdr_base_addr in table
Skylar Chang7fa22712017-04-03 18:29:21 -07001391 * @l2tp_params: l2tp parameters
Amir Levy9659e592016-10-27 18:08:27 +03001392 */
1393int ipahal_cp_proc_ctx_to_hw_buff(enum ipa_hdr_proc_type type,
1394 void *const base, u32 offset, u32 hdr_len,
1395 bool is_hdr_proc_ctx, dma_addr_t phys_base,
Skylar Chang7fa22712017-04-03 18:29:21 -07001396 u32 hdr_base_addr, struct ipa_hdr_offset_entry *offset_entry,
Shihuan Liufe2818b2017-07-03 22:14:55 -07001397 struct ipa_l2tp_hdr_proc_ctx_params l2tp_params)
Amir Levy9659e592016-10-27 18:08:27 +03001398{
1399 IPAHAL_DBG(
1400 "type %d, base %p, offset %d, hdr_len %d, is_hdr_proc_ctx %d, hdr_base_addr %d, offset_entry %p\n"
1401 , type, base, offset, hdr_len, is_hdr_proc_ctx,
1402 hdr_base_addr, offset_entry);
1403
1404 if (!base ||
1405 !hdr_len ||
Gidon Studinski3021a6f2016-11-10 12:48:48 +02001406 (is_hdr_proc_ctx && !phys_base) ||
1407 (!is_hdr_proc_ctx && !offset_entry) ||
1408 (!is_hdr_proc_ctx && !hdr_base_addr)) {
Amir Levy9659e592016-10-27 18:08:27 +03001409 IPAHAL_ERR(
1410 "invalid input: hdr_len:%u phys_base:%pad hdr_base_addr:%u is_hdr_proc_ctx:%d offset_entry:%pK\n"
1411 , hdr_len, &phys_base, hdr_base_addr
1412 , is_hdr_proc_ctx, offset_entry);
1413 return -EINVAL;
1414 }
1415
1416 return hdr_funcs.ipahal_cp_proc_ctx_to_hw_buff(type, base, offset,
1417 hdr_len, is_hdr_proc_ctx, phys_base,
Skylar Chang7fa22712017-04-03 18:29:21 -07001418 hdr_base_addr, offset_entry, l2tp_params);
Amir Levy9659e592016-10-27 18:08:27 +03001419}
1420
1421/*
1422 * ipahal_get_proc_ctx_needed_len() - calculates the needed length for
1423 * addition of header processing context according to the type of processing
1424 * context
1425 * @type: header processing context type (no processing context,
1426 * IPA_HDR_PROC_ETHII_TO_ETHII etc.)
1427 */
1428int ipahal_get_proc_ctx_needed_len(enum ipa_hdr_proc_type type)
1429{
1430 int res;
1431
1432 IPAHAL_DBG("entry\n");
1433
1434 res = hdr_funcs.ipahal_get_proc_ctx_needed_len(type);
1435
1436 IPAHAL_DBG("Exit\n");
1437
1438 return res;
1439}
1440
Ghanim Fodi37b64952017-01-24 15:42:30 +02001441/*
1442 * Get IPA Data Processing Star image memory size at IPA SRAM
1443 */
1444u32 ipahal_get_dps_img_mem_size(void)
1445{
1446 return IPA_HW_DPS_IMG_MEM_SIZE_V3_0;
1447}
1448
1449/*
1450 * Get IPA Header Processing Star image memory size at IPA SRAM
1451 */
1452u32 ipahal_get_hps_img_mem_size(void)
1453{
1454 return IPA_HW_HPS_IMG_MEM_SIZE_V3_0;
1455}
Amir Levy9659e592016-10-27 18:08:27 +03001456
1457int ipahal_init(enum ipa_hw_type ipa_hw_type, void __iomem *base,
1458 struct device *ipa_pdev)
1459{
1460 int result;
1461
1462 IPAHAL_DBG("Entry - IPA HW TYPE=%d base=%p ipa_pdev=%p\n",
1463 ipa_hw_type, base, ipa_pdev);
1464
1465 ipahal_ctx = kzalloc(sizeof(*ipahal_ctx), GFP_KERNEL);
1466 if (!ipahal_ctx) {
1467 IPAHAL_ERR("kzalloc err for ipahal_ctx\n");
1468 result = -ENOMEM;
1469 goto bail_err_exit;
1470 }
1471
1472 if (ipa_hw_type < IPA_HW_v3_0) {
1473 IPAHAL_ERR("ipahal supported on IPAv3 and later only\n");
1474 result = -EINVAL;
1475 goto bail_free_ctx;
1476 }
1477
1478 if (ipa_hw_type >= IPA_HW_MAX) {
1479 IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
1480 result = -EINVAL;
1481 goto bail_free_ctx;
1482 }
1483
1484 if (!base) {
1485 IPAHAL_ERR("invalid memory io mapping addr\n");
1486 result = -EINVAL;
1487 goto bail_free_ctx;
1488 }
1489
1490 if (!ipa_pdev) {
1491 IPAHAL_ERR("invalid IPA platform device\n");
1492 result = -EINVAL;
1493 goto bail_free_ctx;
1494 }
1495
1496 ipahal_ctx->hw_type = ipa_hw_type;
1497 ipahal_ctx->base = base;
1498 ipahal_ctx->ipa_pdev = ipa_pdev;
1499
1500 if (ipahal_reg_init(ipa_hw_type)) {
1501 IPAHAL_ERR("failed to init ipahal reg\n");
1502 result = -EFAULT;
1503 goto bail_free_ctx;
1504 }
1505
1506 if (ipahal_imm_cmd_init(ipa_hw_type)) {
1507 IPAHAL_ERR("failed to init ipahal imm cmd\n");
1508 result = -EFAULT;
1509 goto bail_free_ctx;
1510 }
1511
1512 if (ipahal_pkt_status_init(ipa_hw_type)) {
1513 IPAHAL_ERR("failed to init ipahal pkt status\n");
1514 result = -EFAULT;
1515 goto bail_free_ctx;
1516 }
1517
1518 ipahal_hdr_init(ipa_hw_type);
1519
1520 if (ipahal_fltrt_init(ipa_hw_type)) {
1521 IPAHAL_ERR("failed to init ipahal flt rt\n");
1522 result = -EFAULT;
1523 goto bail_free_ctx;
1524 }
1525
Skylar Chang2c470a62017-07-25 10:10:44 -07001526 if (ipahal_hw_stats_init(ipa_hw_type)) {
1527 IPAHAL_ERR("failed to init ipahal hw stats\n");
1528 result = -EFAULT;
1529 goto bail_free_ctx;
1530 }
1531
Amir Levy9659e592016-10-27 18:08:27 +03001532 ipahal_debugfs_init();
1533
1534 return 0;
1535
1536bail_free_ctx:
1537 kfree(ipahal_ctx);
1538 ipahal_ctx = NULL;
1539bail_err_exit:
1540 return result;
1541}
1542
1543void ipahal_destroy(void)
1544{
1545 IPAHAL_DBG("Entry\n");
1546 ipahal_fltrt_destroy();
1547 ipahal_debugfs_remove();
1548 kfree(ipahal_ctx);
1549 ipahal_ctx = NULL;
1550}
1551
1552void ipahal_free_dma_mem(struct ipa_mem_buffer *mem)
1553{
1554 if (likely(mem)) {
1555 dma_free_coherent(ipahal_ctx->ipa_pdev, mem->size, mem->base,
1556 mem->phys_base);
1557 mem->size = 0;
1558 mem->base = NULL;
1559 mem->phys_base = 0;
1560 }
1561}