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