net/bnxt: support EEM system memory
[dpdk.git] / drivers / net / bnxt / tf_core / tf_msg.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <inttypes.h>
7 #include <stdbool.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "tf_msg_common.h"
12 #include "tf_device.h"
13 #include "tf_msg.h"
14 #include "tf_util.h"
15 #include "tf_common.h"
16 #include "tf_session.h"
17 #include "tfp.h"
18 #include "hwrm_tf.h"
19 #include "tf_em.h"
20
21 /* Logging defines */
22 #define TF_RM_MSG_DEBUG  0
23
24 /**
25  * This is the MAX data we can transport across regular HWRM
26  */
27 #define TF_PCI_BUF_SIZE_MAX 88
28
29 /**
30  * If data bigger than TF_PCI_BUF_SIZE_MAX then use DMA method
31  */
32 struct tf_msg_dma_buf {
33         void *va_addr;
34         uint64_t pa_addr;
35 };
36
37 /**
38  * Allocates a DMA buffer that can be used for message transfer.
39  *
40  * [in] buf
41  *   Pointer to DMA buffer structure
42  *
43  * [in] size
44  *   Requested size of the buffer in bytes
45  *
46  * Returns:
47  *    0      - Success
48  *   -ENOMEM - Unable to allocate buffer, no memory
49  */
50 static int
51 tf_msg_alloc_dma_buf(struct tf_msg_dma_buf *buf, int size)
52 {
53         struct tfp_calloc_parms alloc_parms;
54         int rc;
55
56         /* Allocate session */
57         alloc_parms.nitems = 1;
58         alloc_parms.size = size;
59         alloc_parms.alignment = 4096;
60         rc = tfp_calloc(&alloc_parms);
61         if (rc)
62                 return -ENOMEM;
63
64         buf->pa_addr = (uintptr_t)alloc_parms.mem_pa;
65         buf->va_addr = alloc_parms.mem_va;
66
67         return 0;
68 }
69
70 /**
71  * Free's a previous allocated DMA buffer.
72  *
73  * [in] buf
74  *   Pointer to DMA buffer structure
75  */
76 static void
77 tf_msg_free_dma_buf(struct tf_msg_dma_buf *buf)
78 {
79         tfp_free(buf->va_addr);
80 }
81
82 /* HWRM Direct messages */
83
84 int
85 tf_msg_session_open(struct tf *tfp,
86                     char *ctrl_chan_name,
87                     uint8_t *fw_session_id,
88                     uint8_t *fw_session_client_id)
89 {
90         int rc;
91         struct hwrm_tf_session_open_input req = { 0 };
92         struct hwrm_tf_session_open_output resp = { 0 };
93         struct tfp_send_msg_parms parms = { 0 };
94
95         /* Populate the request */
96         tfp_memcpy(&req.session_name, ctrl_chan_name, TF_SESSION_NAME_MAX);
97
98         parms.tf_type = HWRM_TF_SESSION_OPEN;
99         parms.req_data = (uint32_t *)&req;
100         parms.req_size = sizeof(req);
101         parms.resp_data = (uint32_t *)&resp;
102         parms.resp_size = sizeof(resp);
103         parms.mailbox = TF_KONG_MB;
104
105         rc = tfp_send_msg_direct(tfp,
106                                  &parms);
107         if (rc)
108                 return rc;
109
110         *fw_session_id = (uint8_t)tfp_le_to_cpu_32(resp.fw_session_id);
111         *fw_session_client_id = (uint8_t)tfp_le_to_cpu_32(resp.fw_session_id);
112
113         return rc;
114 }
115
116 int
117 tf_msg_session_attach(struct tf *tfp __rte_unused,
118                       char *ctrl_chan_name __rte_unused,
119                       uint8_t tf_fw_session_id __rte_unused)
120 {
121         return -1;
122 }
123
124 int
125 tf_msg_session_client_register(struct tf *tfp,
126                                char *ctrl_channel_name,
127                                uint8_t *fw_session_client_id)
128 {
129         int rc;
130         struct hwrm_tf_session_register_input req = { 0 };
131         struct hwrm_tf_session_register_output resp = { 0 };
132         struct tfp_send_msg_parms parms = { 0 };
133         uint8_t fw_session_id;
134
135         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
136         if (rc) {
137                 TFP_DRV_LOG(ERR,
138                             "Unable to lookup FW id, rc:%s\n",
139                             strerror(-rc));
140                 return rc;
141         }
142
143         /* Populate the request */
144         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
145         tfp_memcpy(&req.session_client_name,
146                    ctrl_channel_name,
147                    TF_SESSION_NAME_MAX);
148
149         parms.tf_type = HWRM_TF_SESSION_REGISTER;
150         parms.req_data = (uint32_t *)&req;
151         parms.req_size = sizeof(req);
152         parms.resp_data = (uint32_t *)&resp;
153         parms.resp_size = sizeof(resp);
154         parms.mailbox = TF_KONG_MB;
155
156         rc = tfp_send_msg_direct(tfp,
157                                  &parms);
158         if (rc)
159                 return rc;
160
161         *fw_session_client_id =
162                 (uint8_t)tfp_le_to_cpu_32(resp.fw_session_client_id);
163
164         return rc;
165 }
166
167 int
168 tf_msg_session_client_unregister(struct tf *tfp,
169                                  uint8_t fw_session_client_id)
170 {
171         int rc;
172         struct hwrm_tf_session_unregister_input req = { 0 };
173         struct hwrm_tf_session_unregister_output resp = { 0 };
174         struct tfp_send_msg_parms parms = { 0 };
175         uint8_t fw_session_id;
176
177         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
178         if (rc) {
179                 TFP_DRV_LOG(ERR,
180                             "Unable to lookup FW id, rc:%s\n",
181                             strerror(-rc));
182                 return rc;
183         }
184
185         /* Populate the request */
186         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
187         req.fw_session_client_id = tfp_cpu_to_le_32(fw_session_client_id);
188
189         parms.tf_type = HWRM_TF_SESSION_UNREGISTER;
190         parms.req_data = (uint32_t *)&req;
191         parms.req_size = sizeof(req);
192         parms.resp_data = (uint32_t *)&resp;
193         parms.resp_size = sizeof(resp);
194         parms.mailbox = TF_KONG_MB;
195
196         rc = tfp_send_msg_direct(tfp,
197                                  &parms);
198
199         return rc;
200 }
201
202 int
203 tf_msg_session_close(struct tf *tfp)
204 {
205         int rc;
206         struct hwrm_tf_session_close_input req = { 0 };
207         struct hwrm_tf_session_close_output resp = { 0 };
208         struct tfp_send_msg_parms parms = { 0 };
209         uint8_t fw_session_id;
210
211         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
212         if (rc) {
213                 TFP_DRV_LOG(ERR,
214                             "Unable to lookup FW id, rc:%s\n",
215                             strerror(-rc));
216                 return rc;
217         }
218
219         /* Populate the request */
220         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
221
222         parms.tf_type = HWRM_TF_SESSION_CLOSE;
223         parms.req_data = (uint32_t *)&req;
224         parms.req_size = sizeof(req);
225         parms.resp_data = (uint32_t *)&resp;
226         parms.resp_size = sizeof(resp);
227         parms.mailbox = TF_KONG_MB;
228
229         rc = tfp_send_msg_direct(tfp,
230                                  &parms);
231         return rc;
232 }
233
234 int
235 tf_msg_session_qcfg(struct tf *tfp)
236 {
237         int rc;
238         struct hwrm_tf_session_qcfg_input req = { 0 };
239         struct hwrm_tf_session_qcfg_output resp = { 0 };
240         struct tfp_send_msg_parms parms = { 0 };
241         uint8_t fw_session_id;
242
243         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
244         if (rc) {
245                 TFP_DRV_LOG(ERR,
246                             "Unable to lookup FW id, rc:%s\n",
247                             strerror(-rc));
248                 return rc;
249         }
250
251         /* Populate the request */
252         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
253
254         parms.tf_type = HWRM_TF_SESSION_QCFG,
255         parms.req_data = (uint32_t *)&req;
256         parms.req_size = sizeof(req);
257         parms.resp_data = (uint32_t *)&resp;
258         parms.resp_size = sizeof(resp);
259         parms.mailbox = TF_KONG_MB;
260
261         rc = tfp_send_msg_direct(tfp,
262                                  &parms);
263         return rc;
264 }
265
266 int
267 tf_msg_session_resc_qcaps(struct tf *tfp,
268                           enum tf_dir dir,
269                           uint16_t size,
270                           struct tf_rm_resc_req_entry *query,
271                           enum tf_rm_resc_resv_strategy *resv_strategy)
272 {
273         int rc;
274         int i;
275         struct tfp_send_msg_parms parms = { 0 };
276         struct hwrm_tf_session_resc_qcaps_input req = { 0 };
277         struct hwrm_tf_session_resc_qcaps_output resp = { 0 };
278         uint8_t fw_session_id;
279         struct tf_msg_dma_buf qcaps_buf = { 0 };
280         struct tf_rm_resc_req_entry *data;
281         int dma_size;
282
283         TF_CHECK_PARMS3(tfp, query, resv_strategy);
284
285         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
286         if (rc) {
287                 TFP_DRV_LOG(ERR,
288                             "%s: Unable to lookup FW id, rc:%s\n",
289                             tf_dir_2_str(dir),
290                             strerror(-rc));
291                 return rc;
292         }
293
294         /* Prepare DMA buffer */
295         dma_size = size * sizeof(struct tf_rm_resc_req_entry);
296         rc = tf_msg_alloc_dma_buf(&qcaps_buf, dma_size);
297         if (rc)
298                 return rc;
299
300         /* Populate the request */
301         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
302         req.flags = tfp_cpu_to_le_16(dir);
303         req.qcaps_size = size;
304         req.qcaps_addr = tfp_cpu_to_le_64(qcaps_buf.pa_addr);
305
306         parms.tf_type = HWRM_TF_SESSION_RESC_QCAPS;
307         parms.req_data = (uint32_t *)&req;
308         parms.req_size = sizeof(req);
309         parms.resp_data = (uint32_t *)&resp;
310         parms.resp_size = sizeof(resp);
311         parms.mailbox = TF_KONG_MB;
312
313         rc = tfp_send_msg_direct(tfp, &parms);
314         if (rc)
315                 goto cleanup;
316
317         /* Process the response
318          * Should always get expected number of entries
319          */
320         if (tfp_le_to_cpu_32(resp.size) != size) {
321                 TFP_DRV_LOG(ERR,
322                             "%s: QCAPS message size error, rc:%s\n",
323                             tf_dir_2_str(dir),
324                             strerror(-EINVAL));
325                 rc = -EINVAL;
326                 goto cleanup;
327         }
328
329 #if (TF_RM_MSG_DEBUG == 1)
330         printf("size: %d\n", tfp_le_to_cpu_32(resp.size));
331 #endif /* (TF_RM_MSG_DEBUG == 1) */
332
333         /* Post process the response */
334         data = (struct tf_rm_resc_req_entry *)qcaps_buf.va_addr;
335
336 #if (TF_RM_MSG_DEBUG == 1)
337         printf("\nQCAPS\n");
338 #endif /* (TF_RM_MSG_DEBUG == 1) */
339         for (i = 0; i < size; i++) {
340                 query[i].type = tfp_le_to_cpu_32(data[i].type);
341                 query[i].min = tfp_le_to_cpu_16(data[i].min);
342                 query[i].max = tfp_le_to_cpu_16(data[i].max);
343
344 #if (TF_RM_MSG_DEBUG == 1)
345                 printf("type: %d(0x%x) %d %d\n",
346                        query[i].type,
347                        query[i].type,
348                        query[i].min,
349                        query[i].max);
350 #endif /* (TF_RM_MSG_DEBUG == 1) */
351
352         }
353
354         *resv_strategy = resp.flags &
355               HWRM_TF_SESSION_RESC_QCAPS_OUTPUT_FLAGS_SESS_RESV_STRATEGY_MASK;
356
357 cleanup:
358         tf_msg_free_dma_buf(&qcaps_buf);
359
360         return rc;
361 }
362
363 int
364 tf_msg_session_resc_alloc(struct tf *tfp,
365                           enum tf_dir dir,
366                           uint16_t size,
367                           struct tf_rm_resc_req_entry *request,
368                           struct tf_rm_resc_entry *resv)
369 {
370         int rc;
371         int i;
372         struct tfp_send_msg_parms parms = { 0 };
373         struct hwrm_tf_session_resc_alloc_input req = { 0 };
374         struct hwrm_tf_session_resc_alloc_output resp = { 0 };
375         uint8_t fw_session_id;
376         struct tf_msg_dma_buf req_buf = { 0 };
377         struct tf_msg_dma_buf resv_buf = { 0 };
378         struct tf_rm_resc_req_entry *req_data;
379         struct tf_rm_resc_entry *resv_data;
380         int dma_size;
381
382         TF_CHECK_PARMS3(tfp, request, resv);
383
384         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
385         if (rc) {
386                 TFP_DRV_LOG(ERR,
387                             "%s: Unable to lookup FW id, rc:%s\n",
388                             tf_dir_2_str(dir),
389                             strerror(-rc));
390                 return rc;
391         }
392
393         /* Prepare DMA buffers */
394         dma_size = size * sizeof(struct tf_rm_resc_req_entry);
395         rc = tf_msg_alloc_dma_buf(&req_buf, dma_size);
396         if (rc)
397                 return rc;
398
399         dma_size = size * sizeof(struct tf_rm_resc_entry);
400         rc = tf_msg_alloc_dma_buf(&resv_buf, dma_size);
401         if (rc) {
402                 tf_msg_free_dma_buf(&req_buf);
403                 return rc;
404         }
405
406         /* Populate the request */
407         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
408         req.flags = tfp_cpu_to_le_16(dir);
409         req.req_size = size;
410
411         req_data = (struct tf_rm_resc_req_entry *)req_buf.va_addr;
412         for (i = 0; i < size; i++) {
413                 req_data[i].type = tfp_cpu_to_le_32(request[i].type);
414                 req_data[i].min = tfp_cpu_to_le_16(request[i].min);
415                 req_data[i].max = tfp_cpu_to_le_16(request[i].max);
416         }
417
418         req.req_addr = tfp_cpu_to_le_64(req_buf.pa_addr);
419         req.resc_addr = tfp_cpu_to_le_64(resv_buf.pa_addr);
420
421         parms.tf_type = HWRM_TF_SESSION_RESC_ALLOC;
422         parms.req_data = (uint32_t *)&req;
423         parms.req_size = sizeof(req);
424         parms.resp_data = (uint32_t *)&resp;
425         parms.resp_size = sizeof(resp);
426         parms.mailbox = TF_KONG_MB;
427
428         rc = tfp_send_msg_direct(tfp, &parms);
429         if (rc)
430                 goto cleanup;
431
432         /* Process the response
433          * Should always get expected number of entries
434          */
435         if (tfp_le_to_cpu_32(resp.size) != size) {
436                 TFP_DRV_LOG(ERR,
437                             "%s: Alloc message size error, rc:%s\n",
438                             tf_dir_2_str(dir),
439                             strerror(-EINVAL));
440                 rc = -EINVAL;
441                 goto cleanup;
442         }
443
444 #if (TF_RM_MSG_DEBUG == 1)
445         printf("\nRESV\n");
446         printf("size: %d\n", tfp_le_to_cpu_32(resp.size));
447 #endif /* (TF_RM_MSG_DEBUG == 1) */
448
449         /* Post process the response */
450         resv_data = (struct tf_rm_resc_entry *)resv_buf.va_addr;
451         for (i = 0; i < size; i++) {
452                 resv[i].type = tfp_le_to_cpu_32(resv_data[i].type);
453                 resv[i].start = tfp_le_to_cpu_16(resv_data[i].start);
454                 resv[i].stride = tfp_le_to_cpu_16(resv_data[i].stride);
455
456 #if (TF_RM_MSG_DEBUG == 1)
457                 printf("%d type: %d(0x%x) %d %d\n",
458                        i,
459                        resv[i].type,
460                        resv[i].type,
461                        resv[i].start,
462                        resv[i].stride);
463 #endif /* (TF_RM_MSG_DEBUG == 1) */
464         }
465
466 cleanup:
467         tf_msg_free_dma_buf(&req_buf);
468         tf_msg_free_dma_buf(&resv_buf);
469
470         return rc;
471 }
472
473 int
474 tf_msg_session_resc_flush(struct tf *tfp,
475                           enum tf_dir dir,
476                           uint16_t size,
477                           struct tf_rm_resc_entry *resv)
478 {
479         int rc;
480         int i;
481         struct tfp_send_msg_parms parms = { 0 };
482         struct hwrm_tf_session_resc_flush_input req = { 0 };
483         struct hwrm_tf_session_resc_flush_output resp = { 0 };
484         uint8_t fw_session_id;
485         struct tf_msg_dma_buf resv_buf = { 0 };
486         struct tf_rm_resc_entry *resv_data;
487         int dma_size;
488
489         TF_CHECK_PARMS2(tfp, resv);
490
491         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
492         if (rc) {
493                 TFP_DRV_LOG(ERR,
494                             "%s: Unable to lookup FW id, rc:%s\n",
495                             tf_dir_2_str(dir),
496                             strerror(-rc));
497                 return rc;
498         }
499
500         /* Prepare DMA buffers */
501         dma_size = size * sizeof(struct tf_rm_resc_entry);
502         rc = tf_msg_alloc_dma_buf(&resv_buf, dma_size);
503         if (rc)
504                 return rc;
505
506         /* Populate the request */
507         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
508         req.flags = tfp_cpu_to_le_16(dir);
509         req.flush_size = size;
510
511         resv_data = (struct tf_rm_resc_entry *)resv_buf.va_addr;
512         for (i = 0; i < size; i++) {
513                 resv_data[i].type = tfp_cpu_to_le_32(resv[i].type);
514                 resv_data[i].start = tfp_cpu_to_le_16(resv[i].start);
515                 resv_data[i].stride = tfp_cpu_to_le_16(resv[i].stride);
516         }
517
518         req.flush_addr = tfp_cpu_to_le_64(resv_buf.pa_addr);
519
520         parms.tf_type = HWRM_TF_SESSION_RESC_FLUSH;
521         parms.req_data = (uint32_t *)&req;
522         parms.req_size = sizeof(req);
523         parms.resp_data = (uint32_t *)&resp;
524         parms.resp_size = sizeof(resp);
525         parms.mailbox = TF_KONG_MB;
526
527         rc = tfp_send_msg_direct(tfp, &parms);
528
529         tf_msg_free_dma_buf(&resv_buf);
530
531         return rc;
532 }
533
534 int
535 tf_msg_insert_em_internal_entry(struct tf *tfp,
536                                 struct tf_insert_em_entry_parms *em_parms,
537                                 uint16_t *rptr_index,
538                                 uint8_t *rptr_entry,
539                                 uint8_t *num_of_entries)
540 {
541         int rc;
542         struct tfp_send_msg_parms parms = { 0 };
543         struct hwrm_tf_em_insert_input req = { 0 };
544         struct hwrm_tf_em_insert_output resp = { 0 };
545         struct tf_em_64b_entry *em_result =
546                 (struct tf_em_64b_entry *)em_parms->em_record;
547         uint16_t flags;
548         uint8_t fw_session_id;
549
550         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
551         if (rc) {
552                 TFP_DRV_LOG(ERR,
553                             "%s: Unable to lookup FW id, rc:%s\n",
554                             tf_dir_2_str(em_parms->dir),
555                             strerror(-rc));
556                 return rc;
557         }
558
559         /* Populate the request */
560         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
561         tfp_memcpy(req.em_key,
562                    em_parms->key,
563                    ((em_parms->key_sz_in_bits + 7) / 8));
564
565         flags = (em_parms->dir == TF_DIR_TX ?
566                  HWRM_TF_EM_INSERT_INPUT_FLAGS_DIR_TX :
567                  HWRM_TF_EM_INSERT_INPUT_FLAGS_DIR_RX);
568         req.flags = tfp_cpu_to_le_16(flags);
569         req.strength = (em_result->hdr.word1 &
570                         CFA_P4_EEM_ENTRY_STRENGTH_MASK) >>
571                         CFA_P4_EEM_ENTRY_STRENGTH_SHIFT;
572         req.em_key_bitlen = em_parms->key_sz_in_bits;
573         req.action_ptr = em_result->hdr.pointer;
574         req.em_record_idx = *rptr_index;
575
576         parms.tf_type = HWRM_TF_EM_INSERT;
577         parms.req_data = (uint32_t *)&req;
578         parms.req_size = sizeof(req);
579         parms.resp_data = (uint32_t *)&resp;
580         parms.resp_size = sizeof(resp);
581         parms.mailbox = TF_KONG_MB;
582
583         rc = tfp_send_msg_direct(tfp,
584                                  &parms);
585         if (rc)
586                 return rc;
587
588         *rptr_entry = resp.rptr_entry;
589         *rptr_index = resp.rptr_index;
590         *num_of_entries = resp.num_of_entries;
591
592         return 0;
593 }
594
595 int
596 tf_msg_delete_em_entry(struct tf *tfp,
597                        struct tf_delete_em_entry_parms *em_parms)
598 {
599         int rc;
600         struct tfp_send_msg_parms parms = { 0 };
601         struct hwrm_tf_em_delete_input req = { 0 };
602         struct hwrm_tf_em_delete_output resp = { 0 };
603         uint16_t flags;
604         uint8_t fw_session_id;
605
606         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
607         if (rc) {
608                 TFP_DRV_LOG(ERR,
609                             "%s: Unable to lookup FW id, rc:%s\n",
610                             tf_dir_2_str(em_parms->dir),
611                             strerror(-rc));
612                 return rc;
613         }
614
615         /* Populate the request */
616         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
617
618         flags = (em_parms->dir == TF_DIR_TX ?
619                  HWRM_TF_EM_DELETE_INPUT_FLAGS_DIR_TX :
620                  HWRM_TF_EM_DELETE_INPUT_FLAGS_DIR_RX);
621         req.flags = tfp_cpu_to_le_16(flags);
622         req.flow_handle = tfp_cpu_to_le_64(em_parms->flow_handle);
623
624         parms.tf_type = HWRM_TF_EM_DELETE;
625         parms.req_data = (uint32_t *)&req;
626         parms.req_size = sizeof(req);
627         parms.resp_data = (uint32_t *)&resp;
628         parms.resp_size = sizeof(resp);
629         parms.mailbox = TF_KONG_MB;
630
631         rc = tfp_send_msg_direct(tfp,
632                                  &parms);
633         if (rc)
634                 return rc;
635
636         em_parms->index = tfp_le_to_cpu_16(resp.em_index);
637
638         return 0;
639 }
640
641 int
642 tf_msg_em_mem_rgtr(struct tf *tfp,
643                    int page_lvl,
644                    int page_size,
645                    uint64_t dma_addr,
646                    uint16_t *ctx_id)
647 {
648         int rc;
649         struct hwrm_tf_ctxt_mem_rgtr_input req = { 0 };
650         struct hwrm_tf_ctxt_mem_rgtr_output resp = { 0 };
651         struct tfp_send_msg_parms parms = { 0 };
652
653         req.page_level = page_lvl;
654         req.page_size = page_size;
655         req.page_dir = tfp_cpu_to_le_64(dma_addr);
656
657         parms.tf_type = HWRM_TF_CTXT_MEM_RGTR;
658         parms.req_data = (uint32_t *)&req;
659         parms.req_size = sizeof(req);
660         parms.resp_data = (uint32_t *)&resp;
661         parms.resp_size = sizeof(resp);
662         parms.mailbox = TF_KONG_MB;
663
664         rc = tfp_send_msg_direct(tfp,
665                                  &parms);
666         if (rc)
667                 return rc;
668
669         *ctx_id = tfp_le_to_cpu_16(resp.ctx_id);
670
671         return rc;
672 }
673
674 int
675 tf_msg_em_mem_unrgtr(struct tf *tfp,
676                      uint16_t *ctx_id)
677 {
678         int rc;
679         struct hwrm_tf_ctxt_mem_unrgtr_input req = {0};
680         struct hwrm_tf_ctxt_mem_unrgtr_output resp = {0};
681         struct tfp_send_msg_parms parms = { 0 };
682
683         req.ctx_id = tfp_cpu_to_le_32(*ctx_id);
684
685         parms.tf_type = HWRM_TF_CTXT_MEM_UNRGTR;
686         parms.req_data = (uint32_t *)&req;
687         parms.req_size = sizeof(req);
688         parms.resp_data = (uint32_t *)&resp;
689         parms.resp_size = sizeof(resp);
690         parms.mailbox = TF_KONG_MB;
691
692         rc = tfp_send_msg_direct(tfp,
693                                  &parms);
694         return rc;
695 }
696
697 int
698 tf_msg_em_qcaps(struct tf *tfp,
699                 int dir,
700                 struct tf_em_caps *em_caps)
701 {
702         int rc;
703         struct hwrm_tf_ext_em_qcaps_input  req = {0};
704         struct hwrm_tf_ext_em_qcaps_output resp = { 0 };
705         uint32_t             flags;
706         struct tfp_send_msg_parms parms = { 0 };
707
708         flags = (dir == TF_DIR_TX ? HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR_TX :
709                  HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_DIR_RX);
710         req.flags = tfp_cpu_to_le_32(flags);
711
712         parms.tf_type = HWRM_TF_EXT_EM_QCAPS;
713         parms.req_data = (uint32_t *)&req;
714         parms.req_size = sizeof(req);
715         parms.resp_data = (uint32_t *)&resp;
716         parms.resp_size = sizeof(resp);
717         parms.mailbox = TF_KONG_MB;
718
719         rc = tfp_send_msg_direct(tfp,
720                                  &parms);
721         if (rc)
722                 return rc;
723
724         em_caps->supported = tfp_le_to_cpu_32(resp.supported);
725         em_caps->max_entries_supported =
726                 tfp_le_to_cpu_32(resp.max_entries_supported);
727         em_caps->key_entry_size = tfp_le_to_cpu_16(resp.key_entry_size);
728         em_caps->record_entry_size =
729                 tfp_le_to_cpu_16(resp.record_entry_size);
730         em_caps->efc_entry_size = tfp_le_to_cpu_16(resp.efc_entry_size);
731
732         return rc;
733 }
734
735 int
736 tf_msg_em_cfg(struct tf *tfp,
737               uint32_t num_entries,
738               uint16_t key0_ctx_id,
739               uint16_t key1_ctx_id,
740               uint16_t record_ctx_id,
741               uint16_t efc_ctx_id,
742               uint8_t flush_interval,
743               int dir)
744 {
745         int rc;
746         struct hwrm_tf_ext_em_cfg_input  req = {0};
747         struct hwrm_tf_ext_em_cfg_output resp = {0};
748         uint32_t flags;
749         struct tfp_send_msg_parms parms = { 0 };
750
751         flags = (dir == TF_DIR_TX ? HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_TX :
752                  HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_RX);
753         flags |= HWRM_TF_EXT_EM_QCAPS_INPUT_FLAGS_PREFERRED_OFFLOAD;
754
755         req.flags = tfp_cpu_to_le_32(flags);
756         req.num_entries = tfp_cpu_to_le_32(num_entries);
757
758         req.flush_interval = flush_interval;
759
760         req.key0_ctx_id = tfp_cpu_to_le_16(key0_ctx_id);
761         req.key1_ctx_id = tfp_cpu_to_le_16(key1_ctx_id);
762         req.record_ctx_id = tfp_cpu_to_le_16(record_ctx_id);
763         req.efc_ctx_id = tfp_cpu_to_le_16(efc_ctx_id);
764
765         parms.tf_type = HWRM_TF_EXT_EM_CFG;
766         parms.req_data = (uint32_t *)&req;
767         parms.req_size = sizeof(req);
768         parms.resp_data = (uint32_t *)&resp;
769         parms.resp_size = sizeof(resp);
770         parms.mailbox = TF_KONG_MB;
771
772         rc = tfp_send_msg_direct(tfp,
773                                  &parms);
774         return rc;
775 }
776
777 int
778 tf_msg_em_op(struct tf *tfp,
779              int dir,
780              uint16_t op)
781 {
782         int rc;
783         struct hwrm_tf_ext_em_op_input req = {0};
784         struct hwrm_tf_ext_em_op_output resp = {0};
785         uint32_t flags;
786         struct tfp_send_msg_parms parms = { 0 };
787
788         flags = (dir == TF_DIR_TX ? HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_TX :
789                  HWRM_TF_EXT_EM_CFG_INPUT_FLAGS_DIR_RX);
790         req.flags = tfp_cpu_to_le_32(flags);
791         req.op = tfp_cpu_to_le_16(op);
792
793         parms.tf_type = HWRM_TF_EXT_EM_OP;
794         parms.req_data = (uint32_t *)&req;
795         parms.req_size = sizeof(req);
796         parms.resp_data = (uint32_t *)&resp;
797         parms.resp_size = sizeof(resp);
798         parms.mailbox = TF_KONG_MB;
799
800         rc = tfp_send_msg_direct(tfp,
801                                  &parms);
802         return rc;
803 }
804
805 int
806 tf_msg_tcam_entry_set(struct tf *tfp,
807                       struct tf_tcam_set_parms *parms)
808 {
809         int rc;
810         struct tfp_send_msg_parms mparms = { 0 };
811         struct hwrm_tf_tcam_set_input req = { 0 };
812         struct hwrm_tf_tcam_set_output resp = { 0 };
813         struct tf_msg_dma_buf buf = { 0 };
814         uint8_t *data = NULL;
815         int data_size = 0;
816         uint8_t fw_session_id;
817
818         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
819         if (rc) {
820                 TFP_DRV_LOG(ERR,
821                             "%s: Unable to lookup FW id, rc:%s\n",
822                             tf_dir_2_str(parms->dir),
823                             strerror(-rc));
824                 return rc;
825         }
826
827         /* Populate the request */
828         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
829         req.type = parms->hcapi_type;
830         req.idx = tfp_cpu_to_le_16(parms->idx);
831         if (parms->dir == TF_DIR_TX)
832                 req.flags |= HWRM_TF_TCAM_SET_INPUT_FLAGS_DIR_TX;
833
834         req.key_size = parms->key_size;
835         req.mask_offset = parms->key_size;
836         /* Result follows after key and mask, thus multiply by 2 */
837         req.result_offset = 2 * parms->key_size;
838         req.result_size = parms->result_size;
839         data_size = 2 * req.key_size + req.result_size;
840
841         if (data_size <= TF_PCI_BUF_SIZE_MAX) {
842                 /* use pci buffer */
843                 data = &req.dev_data[0];
844         } else {
845                 /* use dma buffer */
846                 req.flags |= HWRM_TF_TCAM_SET_INPUT_FLAGS_DMA;
847                 rc = tf_msg_alloc_dma_buf(&buf, data_size);
848                 if (rc)
849                         goto cleanup;
850                 data = buf.va_addr;
851                 tfp_memcpy(&req.dev_data[0],
852                            &buf.pa_addr,
853                            sizeof(buf.pa_addr));
854         }
855
856         tfp_memcpy(&data[0], parms->key, parms->key_size);
857         tfp_memcpy(&data[parms->key_size], parms->mask, parms->key_size);
858         tfp_memcpy(&data[req.result_offset], parms->result, parms->result_size);
859
860         mparms.tf_type = HWRM_TF_TCAM_SET;
861         mparms.req_data = (uint32_t *)&req;
862         mparms.req_size = sizeof(req);
863         mparms.resp_data = (uint32_t *)&resp;
864         mparms.resp_size = sizeof(resp);
865         mparms.mailbox = TF_KONG_MB;
866
867         rc = tfp_send_msg_direct(tfp,
868                                  &mparms);
869
870 cleanup:
871         tf_msg_free_dma_buf(&buf);
872
873         return rc;
874 }
875
876 int
877 tf_msg_tcam_entry_free(struct tf *tfp,
878                        struct tf_tcam_free_parms *in_parms)
879 {
880         int rc;
881         struct hwrm_tf_tcam_free_input req =  { 0 };
882         struct hwrm_tf_tcam_free_output resp = { 0 };
883         struct tfp_send_msg_parms parms = { 0 };
884         uint8_t fw_session_id;
885
886         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
887         if (rc) {
888                 TFP_DRV_LOG(ERR,
889                             "%s: Unable to lookup FW id, rc:%s\n",
890                             tf_dir_2_str(in_parms->dir),
891                             strerror(-rc));
892                 return rc;
893         }
894
895         /* Populate the request */
896         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
897         req.type = in_parms->hcapi_type;
898         req.count = 1;
899         req.idx_list[0] = tfp_cpu_to_le_16(in_parms->idx);
900         if (in_parms->dir == TF_DIR_TX)
901                 req.flags |= HWRM_TF_TCAM_FREE_INPUT_FLAGS_DIR_TX;
902
903         parms.tf_type = HWRM_TF_TCAM_FREE;
904         parms.req_data = (uint32_t *)&req;
905         parms.req_size = sizeof(req);
906         parms.resp_data = (uint32_t *)&resp;
907         parms.resp_size = sizeof(resp);
908         parms.mailbox = TF_KONG_MB;
909
910         rc = tfp_send_msg_direct(tfp,
911                                  &parms);
912         return rc;
913 }
914
915 int
916 tf_msg_set_tbl_entry(struct tf *tfp,
917                      enum tf_dir dir,
918                      uint16_t hcapi_type,
919                      uint16_t size,
920                      uint8_t *data,
921                      uint32_t index)
922 {
923         int rc;
924         struct hwrm_tf_tbl_type_set_input req = { 0 };
925         struct hwrm_tf_tbl_type_set_output resp = { 0 };
926         struct tfp_send_msg_parms parms = { 0 };
927         uint8_t fw_session_id;
928
929         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
930         if (rc) {
931                 TFP_DRV_LOG(ERR,
932                             "%s: Unable to lookup FW id, rc:%s\n",
933                             tf_dir_2_str(dir),
934                             strerror(-rc));
935                 return rc;
936         }
937
938         /* Populate the request */
939         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
940         req.flags = tfp_cpu_to_le_16(dir);
941         req.type = tfp_cpu_to_le_32(hcapi_type);
942         req.size = tfp_cpu_to_le_16(size);
943         req.index = tfp_cpu_to_le_32(index);
944
945         tfp_memcpy(&req.data,
946                    data,
947                    size);
948
949         parms.tf_type = HWRM_TF_TBL_TYPE_SET;
950         parms.req_data = (uint32_t *)&req;
951         parms.req_size = sizeof(req);
952         parms.resp_data = (uint32_t *)&resp;
953         parms.resp_size = sizeof(resp);
954         parms.mailbox = TF_KONG_MB;
955
956         rc = tfp_send_msg_direct(tfp,
957                                  &parms);
958         if (rc)
959                 return rc;
960
961         return tfp_le_to_cpu_32(parms.tf_resp_code);
962 }
963
964 int
965 tf_msg_get_tbl_entry(struct tf *tfp,
966                      enum tf_dir dir,
967                      uint16_t hcapi_type,
968                      uint16_t size,
969                      uint8_t *data,
970                      uint32_t index)
971 {
972         int rc;
973         struct hwrm_tf_tbl_type_get_input req = { 0 };
974         struct hwrm_tf_tbl_type_get_output resp = { 0 };
975         struct tfp_send_msg_parms parms = { 0 };
976         uint8_t fw_session_id;
977
978         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
979         if (rc) {
980                 TFP_DRV_LOG(ERR,
981                             "%s: Unable to lookup FW id, rc:%s\n",
982                             tf_dir_2_str(dir),
983                             strerror(-rc));
984                 return rc;
985         }
986
987         /* Populate the request */
988         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
989         req.flags = tfp_cpu_to_le_16(dir);
990         req.type = tfp_cpu_to_le_32(hcapi_type);
991         req.index = tfp_cpu_to_le_32(index);
992
993         parms.tf_type = HWRM_TF_TBL_TYPE_GET;
994         parms.req_data = (uint32_t *)&req;
995         parms.req_size = sizeof(req);
996         parms.resp_data = (uint32_t *)&resp;
997         parms.resp_size = sizeof(resp);
998         parms.mailbox = TF_KONG_MB;
999
1000         rc = tfp_send_msg_direct(tfp,
1001                                  &parms);
1002         if (rc)
1003                 return rc;
1004
1005         /* Verify that we got enough buffer to return the requested data */
1006         if (tfp_le_to_cpu_32(resp.size) != size)
1007                 return -EINVAL;
1008
1009         tfp_memcpy(data,
1010                    &resp.data,
1011                    size);
1012
1013         return tfp_le_to_cpu_32(parms.tf_resp_code);
1014 }
1015
1016 /* HWRM Tunneled messages */
1017
1018 int
1019 tf_msg_get_global_cfg(struct tf *tfp,
1020                       struct tf_dev_global_cfg_parms *params)
1021 {
1022         int rc = 0;
1023         struct tfp_send_msg_parms parms = { 0 };
1024         tf_get_global_cfg_input_t req = { 0 };
1025         tf_get_global_cfg_output_t resp = { 0 };
1026         uint32_t flags = 0;
1027         uint8_t fw_session_id;
1028         uint16_t resp_size = 0;
1029
1030         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
1031         if (rc) {
1032                 TFP_DRV_LOG(ERR,
1033                             "%s: Unable to lookup FW id, rc:%s\n",
1034                             tf_dir_2_str(params->dir),
1035                             strerror(-rc));
1036                 return rc;
1037         }
1038
1039         flags = (params->dir == TF_DIR_TX ?
1040                  TF_GET_GLOBAL_CFG_INPUT_FLAGS_DIR_TX :
1041                  TF_GET_GLOBAL_CFG_INPUT_FLAGS_DIR_RX);
1042
1043         /* Populate the request */
1044         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
1045         req.flags = tfp_cpu_to_le_32(flags);
1046         req.type = tfp_cpu_to_le_32(params->type);
1047         req.offset = tfp_cpu_to_le_32(params->offset);
1048         req.size = tfp_cpu_to_le_32(params->config_sz_in_bytes);
1049
1050         MSG_PREP(parms,
1051                  TF_KONG_MB,
1052                  HWRM_TF,
1053                  HWRM_TFT_GET_GLOBAL_CFG,
1054                  req,
1055                  resp);
1056
1057         rc = tfp_send_msg_tunneled(tfp, &parms);
1058
1059         if (rc != 0)
1060                 return rc;
1061
1062         /* Verify that we got enough buffer to return the requested data */
1063         resp_size = tfp_le_to_cpu_16(resp.size);
1064         if (resp_size < params->config_sz_in_bytes)
1065                 return -EINVAL;
1066
1067         if (params->config)
1068                 tfp_memcpy(params->config,
1069                            resp.data,
1070                            resp_size);
1071         else
1072                 return -EFAULT;
1073
1074         return tfp_le_to_cpu_32(parms.tf_resp_code);
1075 }
1076
1077 int
1078 tf_msg_set_global_cfg(struct tf *tfp,
1079                       struct tf_dev_global_cfg_parms *params)
1080 {
1081         int rc = 0;
1082         struct tfp_send_msg_parms parms = { 0 };
1083         tf_set_global_cfg_input_t req = { 0 };
1084         uint32_t flags = 0;
1085         uint8_t fw_session_id;
1086
1087         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
1088         if (rc) {
1089                 TFP_DRV_LOG(ERR,
1090                             "%s: Unable to lookup FW id, rc:%s\n",
1091                             tf_dir_2_str(params->dir),
1092                             strerror(-rc));
1093                 return rc;
1094         }
1095
1096         flags = (params->dir == TF_DIR_TX ?
1097                  TF_SET_GLOBAL_CFG_INPUT_FLAGS_DIR_TX :
1098                  TF_SET_GLOBAL_CFG_INPUT_FLAGS_DIR_RX);
1099
1100         /* Populate the request */
1101         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
1102         req.flags = tfp_cpu_to_le_32(flags);
1103         req.type = tfp_cpu_to_le_32(params->type);
1104         req.offset = tfp_cpu_to_le_32(params->offset);
1105         tfp_memcpy(req.data, params->config,
1106                    params->config_sz_in_bytes);
1107         req.size = tfp_cpu_to_le_32(params->config_sz_in_bytes);
1108
1109         MSG_PREP_NO_RESP(parms,
1110                          TF_KONG_MB,
1111                          HWRM_TF,
1112                          HWRM_TFT_SET_GLOBAL_CFG,
1113                          req);
1114
1115         rc = tfp_send_msg_tunneled(tfp, &parms);
1116
1117         if (rc != 0)
1118                 return rc;
1119
1120         return tfp_le_to_cpu_32(parms.tf_resp_code);
1121 }
1122
1123 int
1124 tf_msg_bulk_get_tbl_entry(struct tf *tfp,
1125                           enum tf_dir dir,
1126                           uint16_t hcapi_type,
1127                           uint32_t starting_idx,
1128                           uint16_t num_entries,
1129                           uint16_t entry_sz_in_bytes,
1130                           uint64_t physical_mem_addr)
1131 {
1132         int rc;
1133         struct tfp_send_msg_parms parms = { 0 };
1134         struct tf_tbl_type_bulk_get_input req = { 0 };
1135         struct tf_tbl_type_bulk_get_output resp = { 0 };
1136         int data_size = 0;
1137         uint8_t fw_session_id;
1138
1139         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
1140         if (rc) {
1141                 TFP_DRV_LOG(ERR,
1142                             "%s: Unable to lookup FW id, rc:%s\n",
1143                             tf_dir_2_str(dir),
1144                             strerror(-rc));
1145                 return rc;
1146         }
1147
1148         /* Populate the request */
1149         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
1150         req.flags = tfp_cpu_to_le_16(dir);
1151         req.type = tfp_cpu_to_le_32(hcapi_type);
1152         req.start_index = tfp_cpu_to_le_32(starting_idx);
1153         req.num_entries = tfp_cpu_to_le_32(num_entries);
1154
1155         data_size = num_entries * entry_sz_in_bytes;
1156
1157         req.host_addr = tfp_cpu_to_le_64(physical_mem_addr);
1158
1159         MSG_PREP(parms,
1160                  TF_KONG_MB,
1161                  HWRM_TF,
1162                  HWRM_TFT_TBL_TYPE_BULK_GET,
1163                  req,
1164                  resp);
1165
1166         rc = tfp_send_msg_tunneled(tfp, &parms);
1167         if (rc)
1168                 return rc;
1169
1170         /* Verify that we got enough buffer to return the requested data */
1171         if (tfp_le_to_cpu_32(resp.size) != data_size)
1172                 return -EINVAL;
1173
1174         return tfp_le_to_cpu_32(parms.tf_resp_code);
1175 }
1176
1177 int
1178 tf_msg_get_if_tbl_entry(struct tf *tfp,
1179                         struct tf_if_tbl_get_parms *params)
1180 {
1181         int rc = 0;
1182         struct tfp_send_msg_parms parms = { 0 };
1183         tf_if_tbl_get_input_t req = { 0 };
1184         tf_if_tbl_get_output_t resp;
1185         uint32_t flags = 0;
1186         struct tf_session *tfs;
1187
1188         /* Retrieve the session information */
1189         rc = tf_session_get_session(tfp, &tfs);
1190         if (rc) {
1191                 TFP_DRV_LOG(ERR,
1192                             "%s: Failed to lookup session, rc:%s\n",
1193                             tf_dir_2_str(params->dir),
1194                             strerror(-rc));
1195                 return rc;
1196         }
1197
1198         flags = (params->dir == TF_DIR_TX ? TF_IF_TBL_GET_INPUT_FLAGS_DIR_TX :
1199                  TF_IF_TBL_GET_INPUT_FLAGS_DIR_RX);
1200
1201         /* Populate the request */
1202         req.fw_session_id =
1203                 tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
1204         req.flags = flags;
1205         req.tf_if_tbl_type = params->hcapi_type;
1206         req.idx = tfp_cpu_to_le_16(params->idx);
1207         req.data_sz_in_bytes = tfp_cpu_to_le_16(params->data_sz_in_bytes);
1208
1209         MSG_PREP(parms,
1210                  TF_KONG_MB,
1211                  HWRM_TF,
1212                  HWRM_TFT_IF_TBL_GET,
1213                  req,
1214                  resp);
1215
1216         rc = tfp_send_msg_tunneled(tfp, &parms);
1217
1218         if (rc != 0)
1219                 return rc;
1220
1221         if (parms.tf_resp_code != 0)
1222                 return tfp_le_to_cpu_32(parms.tf_resp_code);
1223
1224         tfp_memcpy(&params->data[0], resp.data, req.data_sz_in_bytes);
1225
1226         return tfp_le_to_cpu_32(parms.tf_resp_code);
1227 }
1228
1229 int
1230 tf_msg_set_if_tbl_entry(struct tf *tfp,
1231                         struct tf_if_tbl_set_parms *params)
1232 {
1233         int rc = 0;
1234         struct tfp_send_msg_parms parms = { 0 };
1235         tf_if_tbl_set_input_t req = { 0 };
1236         uint32_t flags = 0;
1237         struct tf_session *tfs;
1238
1239         /* Retrieve the session information */
1240         rc = tf_session_get_session(tfp, &tfs);
1241         if (rc) {
1242                 TFP_DRV_LOG(ERR,
1243                             "%s: Failed to lookup session, rc:%s\n",
1244                             tf_dir_2_str(params->dir),
1245                             strerror(-rc));
1246                 return rc;
1247         }
1248
1249
1250         flags = (params->dir == TF_DIR_TX ? TF_IF_TBL_SET_INPUT_FLAGS_DIR_TX :
1251                  TF_IF_TBL_SET_INPUT_FLAGS_DIR_RX);
1252
1253         /* Populate the request */
1254         req.fw_session_id =
1255                 tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
1256         req.flags = flags;
1257         req.tf_if_tbl_type = params->hcapi_type;
1258         req.idx = tfp_cpu_to_le_32(params->idx);
1259         req.data_sz_in_bytes = tfp_cpu_to_le_32(params->data_sz_in_bytes);
1260         tfp_memcpy(&req.data[0], params->data, params->data_sz_in_bytes);
1261
1262         MSG_PREP_NO_RESP(parms,
1263                          TF_KONG_MB,
1264                          HWRM_TF,
1265                          HWRM_TFT_IF_TBL_SET,
1266                          req);
1267
1268         rc = tfp_send_msg_tunneled(tfp, &parms);
1269
1270         if (rc != 0)
1271                 return rc;
1272
1273         return tfp_le_to_cpu_32(parms.tf_resp_code);
1274 }