035c0948d150feae3a248f500dcf939d3279ed46
[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
817         req.type = parms->hcapi_type;
818         req.idx = tfp_cpu_to_le_16(parms->idx);
819         if (parms->dir == TF_DIR_TX)
820                 req.flags |= HWRM_TF_TCAM_SET_INPUT_FLAGS_DIR_TX;
821
822         req.key_size = parms->key_size;
823         req.mask_offset = parms->key_size;
824         /* Result follows after key and mask, thus multiply by 2 */
825         req.result_offset = 2 * parms->key_size;
826         req.result_size = parms->result_size;
827         data_size = 2 * req.key_size + req.result_size;
828
829         if (data_size <= TF_PCI_BUF_SIZE_MAX) {
830                 /* use pci buffer */
831                 data = &req.dev_data[0];
832         } else {
833                 /* use dma buffer */
834                 req.flags |= HWRM_TF_TCAM_SET_INPUT_FLAGS_DMA;
835                 rc = tf_msg_alloc_dma_buf(&buf, data_size);
836                 if (rc)
837                         goto cleanup;
838                 data = buf.va_addr;
839                 tfp_memcpy(&req.dev_data[0],
840                            &buf.pa_addr,
841                            sizeof(buf.pa_addr));
842         }
843
844         tfp_memcpy(&data[0], parms->key, parms->key_size);
845         tfp_memcpy(&data[parms->key_size], parms->mask, parms->key_size);
846         tfp_memcpy(&data[req.result_offset], parms->result, parms->result_size);
847
848         mparms.tf_type = HWRM_TF_TCAM_SET;
849         mparms.req_data = (uint32_t *)&req;
850         mparms.req_size = sizeof(req);
851         mparms.resp_data = (uint32_t *)&resp;
852         mparms.resp_size = sizeof(resp);
853         mparms.mailbox = TF_KONG_MB;
854
855         rc = tfp_send_msg_direct(tfp,
856                                  &mparms);
857
858 cleanup:
859         tf_msg_free_dma_buf(&buf);
860
861         return rc;
862 }
863
864 int
865 tf_msg_tcam_entry_free(struct tf *tfp,
866                        struct tf_tcam_free_parms *in_parms)
867 {
868         int rc;
869         struct hwrm_tf_tcam_free_input req =  { 0 };
870         struct hwrm_tf_tcam_free_output resp = { 0 };
871         struct tfp_send_msg_parms parms = { 0 };
872
873         req.type = in_parms->hcapi_type;
874         req.count = 1;
875         req.idx_list[0] = tfp_cpu_to_le_16(in_parms->idx);
876         if (in_parms->dir == TF_DIR_TX)
877                 req.flags |= HWRM_TF_TCAM_FREE_INPUT_FLAGS_DIR_TX;
878
879         parms.tf_type = HWRM_TF_TCAM_FREE;
880         parms.req_data = (uint32_t *)&req;
881         parms.req_size = sizeof(req);
882         parms.resp_data = (uint32_t *)&resp;
883         parms.resp_size = sizeof(resp);
884         parms.mailbox = TF_KONG_MB;
885
886         rc = tfp_send_msg_direct(tfp,
887                                  &parms);
888         return rc;
889 }
890
891 int
892 tf_msg_set_tbl_entry(struct tf *tfp,
893                      enum tf_dir dir,
894                      uint16_t hcapi_type,
895                      uint16_t size,
896                      uint8_t *data,
897                      uint32_t index)
898 {
899         int rc;
900         struct hwrm_tf_tbl_type_set_input req = { 0 };
901         struct hwrm_tf_tbl_type_set_output resp = { 0 };
902         struct tfp_send_msg_parms parms = { 0 };
903         uint8_t fw_session_id;
904
905         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
906         if (rc) {
907                 TFP_DRV_LOG(ERR,
908                             "%s: Unable to lookup FW id, rc:%s\n",
909                             tf_dir_2_str(dir),
910                             strerror(-rc));
911                 return rc;
912         }
913
914         /* Populate the request */
915         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
916         req.flags = tfp_cpu_to_le_16(dir);
917         req.type = tfp_cpu_to_le_32(hcapi_type);
918         req.size = tfp_cpu_to_le_16(size);
919         req.index = tfp_cpu_to_le_32(index);
920
921         tfp_memcpy(&req.data,
922                    data,
923                    size);
924
925         parms.tf_type = HWRM_TF_TBL_TYPE_SET;
926         parms.req_data = (uint32_t *)&req;
927         parms.req_size = sizeof(req);
928         parms.resp_data = (uint32_t *)&resp;
929         parms.resp_size = sizeof(resp);
930         parms.mailbox = TF_KONG_MB;
931
932         rc = tfp_send_msg_direct(tfp,
933                                  &parms);
934         if (rc)
935                 return rc;
936
937         return tfp_le_to_cpu_32(parms.tf_resp_code);
938 }
939
940 int
941 tf_msg_get_tbl_entry(struct tf *tfp,
942                      enum tf_dir dir,
943                      uint16_t hcapi_type,
944                      uint16_t size,
945                      uint8_t *data,
946                      uint32_t index)
947 {
948         int rc;
949         struct hwrm_tf_tbl_type_get_input req = { 0 };
950         struct hwrm_tf_tbl_type_get_output resp = { 0 };
951         struct tfp_send_msg_parms parms = { 0 };
952         uint8_t fw_session_id;
953
954         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
955         if (rc) {
956                 TFP_DRV_LOG(ERR,
957                             "%s: Unable to lookup FW id, rc:%s\n",
958                             tf_dir_2_str(dir),
959                             strerror(-rc));
960                 return rc;
961         }
962
963         /* Populate the request */
964         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
965         req.flags = tfp_cpu_to_le_16(dir);
966         req.type = tfp_cpu_to_le_32(hcapi_type);
967         req.index = tfp_cpu_to_le_32(index);
968
969         parms.tf_type = HWRM_TF_TBL_TYPE_GET;
970         parms.req_data = (uint32_t *)&req;
971         parms.req_size = sizeof(req);
972         parms.resp_data = (uint32_t *)&resp;
973         parms.resp_size = sizeof(resp);
974         parms.mailbox = TF_KONG_MB;
975
976         rc = tfp_send_msg_direct(tfp,
977                                  &parms);
978         if (rc)
979                 return rc;
980
981         /* Verify that we got enough buffer to return the requested data */
982         if (tfp_le_to_cpu_32(resp.size) != size)
983                 return -EINVAL;
984
985         tfp_memcpy(data,
986                    &resp.data,
987                    size);
988
989         return tfp_le_to_cpu_32(parms.tf_resp_code);
990 }
991
992 /* HWRM Tunneled messages */
993
994 int
995 tf_msg_get_global_cfg(struct tf *tfp,
996                       struct tf_dev_global_cfg_parms *params)
997 {
998         int rc = 0;
999         struct tfp_send_msg_parms parms = { 0 };
1000         tf_get_global_cfg_input_t req = { 0 };
1001         tf_get_global_cfg_output_t resp = { 0 };
1002         uint32_t flags = 0;
1003         uint8_t fw_session_id;
1004         uint16_t resp_size = 0;
1005
1006         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
1007         if (rc) {
1008                 TFP_DRV_LOG(ERR,
1009                             "%s: Unable to lookup FW id, rc:%s\n",
1010                             tf_dir_2_str(params->dir),
1011                             strerror(-rc));
1012                 return rc;
1013         }
1014
1015         flags = (params->dir == TF_DIR_TX ?
1016                  TF_GET_GLOBAL_CFG_INPUT_FLAGS_DIR_TX :
1017                  TF_GET_GLOBAL_CFG_INPUT_FLAGS_DIR_RX);
1018
1019         /* Populate the request */
1020         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
1021         req.flags = tfp_cpu_to_le_32(flags);
1022         req.type = tfp_cpu_to_le_32(params->type);
1023         req.offset = tfp_cpu_to_le_32(params->offset);
1024         req.size = tfp_cpu_to_le_32(params->config_sz_in_bytes);
1025
1026         MSG_PREP(parms,
1027                  TF_KONG_MB,
1028                  HWRM_TF,
1029                  HWRM_TFT_GET_GLOBAL_CFG,
1030                  req,
1031                  resp);
1032
1033         rc = tfp_send_msg_tunneled(tfp, &parms);
1034
1035         if (rc != 0)
1036                 return rc;
1037
1038         /* Verify that we got enough buffer to return the requested data */
1039         resp_size = tfp_le_to_cpu_16(resp.size);
1040         if (resp_size < params->config_sz_in_bytes)
1041                 return -EINVAL;
1042
1043         if (params->config)
1044                 tfp_memcpy(params->config,
1045                            resp.data,
1046                            resp_size);
1047         else
1048                 return -EFAULT;
1049
1050         return tfp_le_to_cpu_32(parms.tf_resp_code);
1051 }
1052
1053 int
1054 tf_msg_set_global_cfg(struct tf *tfp,
1055                       struct tf_dev_global_cfg_parms *params)
1056 {
1057         int rc = 0;
1058         struct tfp_send_msg_parms parms = { 0 };
1059         tf_set_global_cfg_input_t req = { 0 };
1060         uint32_t flags = 0;
1061         uint8_t fw_session_id;
1062
1063         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
1064         if (rc) {
1065                 TFP_DRV_LOG(ERR,
1066                             "%s: Unable to lookup FW id, rc:%s\n",
1067                             tf_dir_2_str(params->dir),
1068                             strerror(-rc));
1069                 return rc;
1070         }
1071
1072         flags = (params->dir == TF_DIR_TX ?
1073                  TF_SET_GLOBAL_CFG_INPUT_FLAGS_DIR_TX :
1074                  TF_SET_GLOBAL_CFG_INPUT_FLAGS_DIR_RX);
1075
1076         /* Populate the request */
1077         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
1078         req.flags = tfp_cpu_to_le_32(flags);
1079         req.type = tfp_cpu_to_le_32(params->type);
1080         req.offset = tfp_cpu_to_le_32(params->offset);
1081         tfp_memcpy(req.data, params->config,
1082                    params->config_sz_in_bytes);
1083         req.size = tfp_cpu_to_le_32(params->config_sz_in_bytes);
1084
1085         MSG_PREP_NO_RESP(parms,
1086                          TF_KONG_MB,
1087                          HWRM_TF,
1088                          HWRM_TFT_SET_GLOBAL_CFG,
1089                          req);
1090
1091         rc = tfp_send_msg_tunneled(tfp, &parms);
1092
1093         if (rc != 0)
1094                 return rc;
1095
1096         return tfp_le_to_cpu_32(parms.tf_resp_code);
1097 }
1098
1099 int
1100 tf_msg_bulk_get_tbl_entry(struct tf *tfp,
1101                           enum tf_dir dir,
1102                           uint16_t hcapi_type,
1103                           uint32_t starting_idx,
1104                           uint16_t num_entries,
1105                           uint16_t entry_sz_in_bytes,
1106                           uint64_t physical_mem_addr)
1107 {
1108         int rc;
1109         struct tfp_send_msg_parms parms = { 0 };
1110         struct tf_tbl_type_bulk_get_input req = { 0 };
1111         struct tf_tbl_type_bulk_get_output resp = { 0 };
1112         int data_size = 0;
1113         uint8_t fw_session_id;
1114
1115         rc = tf_session_get_fw_session_id(tfp, &fw_session_id);
1116         if (rc) {
1117                 TFP_DRV_LOG(ERR,
1118                             "%s: Unable to lookup FW id, rc:%s\n",
1119                             tf_dir_2_str(dir),
1120                             strerror(-rc));
1121                 return rc;
1122         }
1123
1124         /* Populate the request */
1125         req.fw_session_id = tfp_cpu_to_le_32(fw_session_id);
1126         req.flags = tfp_cpu_to_le_16(dir);
1127         req.type = tfp_cpu_to_le_32(hcapi_type);
1128         req.start_index = tfp_cpu_to_le_32(starting_idx);
1129         req.num_entries = tfp_cpu_to_le_32(num_entries);
1130
1131         data_size = num_entries * entry_sz_in_bytes;
1132
1133         req.host_addr = tfp_cpu_to_le_64(physical_mem_addr);
1134
1135         MSG_PREP(parms,
1136                  TF_KONG_MB,
1137                  HWRM_TF,
1138                  HWRM_TFT_TBL_TYPE_BULK_GET,
1139                  req,
1140                  resp);
1141
1142         rc = tfp_send_msg_tunneled(tfp, &parms);
1143         if (rc)
1144                 return rc;
1145
1146         /* Verify that we got enough buffer to return the requested data */
1147         if (tfp_le_to_cpu_32(resp.size) != data_size)
1148                 return -EINVAL;
1149
1150         return tfp_le_to_cpu_32(parms.tf_resp_code);
1151 }
1152
1153 int
1154 tf_msg_get_if_tbl_entry(struct tf *tfp,
1155                         struct tf_if_tbl_get_parms *params)
1156 {
1157         int rc = 0;
1158         struct tfp_send_msg_parms parms = { 0 };
1159         tf_if_tbl_get_input_t req = { 0 };
1160         tf_if_tbl_get_output_t resp;
1161         uint32_t flags = 0;
1162         struct tf_session *tfs;
1163
1164         /* Retrieve the session information */
1165         rc = tf_session_get_session(tfp, &tfs);
1166         if (rc) {
1167                 TFP_DRV_LOG(ERR,
1168                             "%s: Failed to lookup session, rc:%s\n",
1169                             tf_dir_2_str(params->dir),
1170                             strerror(-rc));
1171                 return rc;
1172         }
1173
1174         flags = (params->dir == TF_DIR_TX ? TF_IF_TBL_GET_INPUT_FLAGS_DIR_TX :
1175                  TF_IF_TBL_GET_INPUT_FLAGS_DIR_RX);
1176
1177         /* Populate the request */
1178         req.fw_session_id =
1179                 tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
1180         req.flags = flags;
1181         req.tf_if_tbl_type = params->hcapi_type;
1182         req.idx = tfp_cpu_to_le_16(params->idx);
1183         req.data_sz_in_bytes = tfp_cpu_to_le_16(params->data_sz_in_bytes);
1184
1185         MSG_PREP(parms,
1186                  TF_KONG_MB,
1187                  HWRM_TF,
1188                  HWRM_TFT_IF_TBL_GET,
1189                  req,
1190                  resp);
1191
1192         rc = tfp_send_msg_tunneled(tfp, &parms);
1193
1194         if (rc != 0)
1195                 return rc;
1196
1197         if (parms.tf_resp_code != 0)
1198                 return tfp_le_to_cpu_32(parms.tf_resp_code);
1199
1200         tfp_memcpy(&params->data[0], resp.data, req.data_sz_in_bytes);
1201
1202         return tfp_le_to_cpu_32(parms.tf_resp_code);
1203 }
1204
1205 int
1206 tf_msg_set_if_tbl_entry(struct tf *tfp,
1207                         struct tf_if_tbl_set_parms *params)
1208 {
1209         int rc = 0;
1210         struct tfp_send_msg_parms parms = { 0 };
1211         tf_if_tbl_set_input_t req = { 0 };
1212         uint32_t flags = 0;
1213         struct tf_session *tfs;
1214
1215         /* Retrieve the session information */
1216         rc = tf_session_get_session(tfp, &tfs);
1217         if (rc) {
1218                 TFP_DRV_LOG(ERR,
1219                             "%s: Failed to lookup session, rc:%s\n",
1220                             tf_dir_2_str(params->dir),
1221                             strerror(-rc));
1222                 return rc;
1223         }
1224
1225
1226         flags = (params->dir == TF_DIR_TX ? TF_IF_TBL_SET_INPUT_FLAGS_DIR_TX :
1227                  TF_IF_TBL_SET_INPUT_FLAGS_DIR_RX);
1228
1229         /* Populate the request */
1230         req.fw_session_id =
1231                 tfp_cpu_to_le_32(tfs->session_id.internal.fw_session_id);
1232         req.flags = flags;
1233         req.tf_if_tbl_type = params->hcapi_type;
1234         req.idx = tfp_cpu_to_le_32(params->idx);
1235         req.data_sz_in_bytes = tfp_cpu_to_le_32(params->data_sz_in_bytes);
1236         tfp_memcpy(&req.data[0], params->data, params->data_sz_in_bytes);
1237
1238         MSG_PREP_NO_RESP(parms,
1239                          TF_KONG_MB,
1240                          HWRM_TF,
1241                          HWRM_TFT_IF_TBL_SET,
1242                          req);
1243
1244         rc = tfp_send_msg_tunneled(tfp, &parms);
1245
1246         if (rc != 0)
1247                 return rc;
1248
1249         return tfp_le_to_cpu_32(parms.tf_resp_code);
1250 }