baseband/la12xx: add queue and modem config
[dpdk.git] / drivers / baseband / la12xx / bbdev_la12xx.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2020-2021 NXP
3  */
4
5 #include <string.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <sys/ioctl.h>
9 #include <sys/mman.h>
10 #include <dirent.h>
11
12 #include <rte_common.h>
13 #include <rte_bus_vdev.h>
14 #include <rte_malloc.h>
15 #include <rte_ring.h>
16 #include <rte_kvargs.h>
17
18 #include <rte_bbdev.h>
19 #include <rte_bbdev_pmd.h>
20
21 #include <bbdev_la12xx_pmd_logs.h>
22 #include <bbdev_la12xx_ipc.h>
23 #include <bbdev_la12xx.h>
24
25 #define DRIVER_NAME baseband_la12xx
26
27 /*  Initialisation params structure that can be used by LA12xx BBDEV driver */
28 struct bbdev_la12xx_params {
29         uint8_t queues_num; /*< LA12xx BBDEV queues number */
30         int8_t modem_id; /*< LA12xx modem instance id */
31 };
32
33 #define LA12XX_MAX_NB_QUEUES_ARG        "max_nb_queues"
34 #define LA12XX_VDEV_MODEM_ID_ARG        "modem"
35 #define LA12XX_MAX_MODEM 4
36
37 #define LA12XX_MAX_CORES        4
38 #define LA12XX_LDPC_ENC_CORE    0
39 #define LA12XX_LDPC_DEC_CORE    1
40
41 #define LA12XX_MAX_LDPC_ENC_QUEUES      4
42 #define LA12XX_MAX_LDPC_DEC_QUEUES      4
43
44 static const char * const bbdev_la12xx_valid_params[] = {
45         LA12XX_MAX_NB_QUEUES_ARG,
46         LA12XX_VDEV_MODEM_ID_ARG,
47 };
48
49 static const struct rte_bbdev_op_cap bbdev_capabilities[] = {
50         {
51                 .type   = RTE_BBDEV_OP_LDPC_ENC,
52                 .cap.ldpc_enc = {
53                         .capability_flags =
54                                         RTE_BBDEV_LDPC_RATE_MATCH |
55                                         RTE_BBDEV_LDPC_CRC_24A_ATTACH |
56                                         RTE_BBDEV_LDPC_CRC_24B_ATTACH,
57                         .num_buffers_src =
58                                         RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
59                         .num_buffers_dst =
60                                         RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
61                 }
62         },
63         {
64                 .type   = RTE_BBDEV_OP_LDPC_DEC,
65                 .cap.ldpc_dec = {
66                         .capability_flags =
67                                 RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK |
68                                         RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
69                                         RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP,
70                         .num_buffers_src =
71                                         RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
72                         .num_buffers_hard_out =
73                                         RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
74                         .llr_size = 8,
75                         .llr_decimals = 1,
76                 }
77         },
78         RTE_BBDEV_END_OF_CAPABILITIES_LIST()
79 };
80
81 static struct rte_bbdev_queue_conf default_queue_conf = {
82         .queue_size = MAX_CHANNEL_DEPTH,
83 };
84
85 /* Get device info */
86 static void
87 la12xx_info_get(struct rte_bbdev *dev __rte_unused,
88                 struct rte_bbdev_driver_info *dev_info)
89 {
90         PMD_INIT_FUNC_TRACE();
91
92         dev_info->driver_name = RTE_STR(DRIVER_NAME);
93         dev_info->max_num_queues = LA12XX_MAX_QUEUES;
94         dev_info->queue_size_lim = MAX_CHANNEL_DEPTH;
95         dev_info->hardware_accelerated = true;
96         dev_info->max_dl_queue_priority = 0;
97         dev_info->max_ul_queue_priority = 0;
98         dev_info->data_endianness = RTE_BIG_ENDIAN;
99         dev_info->default_queue_conf = default_queue_conf;
100         dev_info->capabilities = bbdev_capabilities;
101         dev_info->cpu_flag_reqs = NULL;
102         dev_info->min_alignment = 64;
103
104         rte_bbdev_log_debug("got device info from %u", dev->data->dev_id);
105 }
106
107 /* Release queue */
108 static int
109 la12xx_queue_release(struct rte_bbdev *dev, uint16_t q_id)
110 {
111         RTE_SET_USED(dev);
112         RTE_SET_USED(q_id);
113
114         PMD_INIT_FUNC_TRACE();
115
116         return 0;
117 }
118
119 #define HUGEPG_OFFSET(A) \
120                 ((uint64_t) ((unsigned long) (A) \
121                 - ((uint64_t)ipc_priv->hugepg_start.host_vaddr)))
122
123 static int
124 ipc_queue_configure(uint32_t channel_id,
125                     ipc_t instance,
126                     struct bbdev_la12xx_q_priv *q_priv)
127 {
128         ipc_userspace_t *ipc_priv = (ipc_userspace_t *)instance;
129         ipc_instance_t *ipc_instance = ipc_priv->instance;
130         ipc_ch_t *ch;
131         void *vaddr;
132         uint32_t i = 0;
133         uint32_t msg_size = sizeof(struct bbdev_ipc_enqueue_op);
134
135         PMD_INIT_FUNC_TRACE();
136
137         rte_bbdev_log_debug("%x %p", ipc_instance->initialized,
138                 ipc_priv->instance);
139         ch = &(ipc_instance->ch_list[channel_id]);
140
141         rte_bbdev_log_debug("channel: %u, depth: %u, msg size: %u",
142                 channel_id, q_priv->queue_size, msg_size);
143
144         /* Start init of channel */
145         ch->md.ring_size = rte_cpu_to_be_32(q_priv->queue_size);
146         ch->md.pi = 0;
147         ch->md.ci = 0;
148         ch->md.msg_size = msg_size;
149         for (i = 0; i < q_priv->queue_size; i++) {
150                 vaddr = rte_malloc(NULL, msg_size, RTE_CACHE_LINE_SIZE);
151                 if (!vaddr)
152                         return IPC_HOST_BUF_ALLOC_FAIL;
153                 /* Only offset now */
154                 ch->bd_h[i].modem_ptr =
155                         rte_cpu_to_be_32(HUGEPG_OFFSET(vaddr));
156                 ch->bd_h[i].host_virt_l = lower_32_bits(vaddr);
157                 ch->bd_h[i].host_virt_h = upper_32_bits(vaddr);
158                 q_priv->msg_ch_vaddr[i] = vaddr;
159                 /* Not sure use of this len may be for CRC*/
160                 ch->bd_h[i].len = 0;
161         }
162         ch->host_ipc_params =
163                 rte_cpu_to_be_32(HUGEPG_OFFSET(q_priv->host_params));
164
165         rte_bbdev_log_debug("Channel configured");
166         return IPC_SUCCESS;
167 }
168
169 static int
170 la12xx_e200_queue_setup(struct rte_bbdev *dev,
171                 struct bbdev_la12xx_q_priv *q_priv)
172 {
173         struct bbdev_la12xx_private *priv = dev->data->dev_private;
174         ipc_userspace_t *ipc_priv = priv->ipc_priv;
175         struct gul_hif *mhif;
176         ipc_metadata_t *ipc_md;
177         ipc_ch_t *ch;
178         int instance_id = 0, i;
179         int ret;
180
181         PMD_INIT_FUNC_TRACE();
182
183         switch (q_priv->op_type) {
184         case RTE_BBDEV_OP_LDPC_ENC:
185                 q_priv->la12xx_core_id = LA12XX_LDPC_ENC_CORE;
186                 break;
187         case RTE_BBDEV_OP_LDPC_DEC:
188                 q_priv->la12xx_core_id = LA12XX_LDPC_DEC_CORE;
189                 break;
190         default:
191                 rte_bbdev_log(ERR, "Unsupported op type\n");
192                 return -1;
193         }
194
195         mhif = (struct gul_hif *)ipc_priv->mhif_start.host_vaddr;
196         /* offset is from start of PEB */
197         ipc_md = (ipc_metadata_t *)((uintptr_t)ipc_priv->peb_start.host_vaddr +
198                 mhif->ipc_regs.ipc_mdata_offset);
199         ch = &ipc_md->instance_list[instance_id].ch_list[q_priv->q_id];
200
201         if (q_priv->q_id < priv->num_valid_queues) {
202                 ipc_br_md_t *md = &(ch->md);
203
204                 q_priv->feca_blk_id = rte_cpu_to_be_32(ch->feca_blk_id);
205                 q_priv->feca_blk_id_be32 = ch->feca_blk_id;
206                 q_priv->host_pi = rte_be_to_cpu_32(md->pi);
207                 q_priv->host_ci = rte_be_to_cpu_32(md->ci);
208                 q_priv->host_params = (host_ipc_params_t *)(uintptr_t)
209                         (rte_be_to_cpu_32(ch->host_ipc_params) +
210                         ((uint64_t)ipc_priv->hugepg_start.host_vaddr));
211
212                 for (i = 0; i < q_priv->queue_size; i++) {
213                         uint32_t h, l;
214
215                         h = ch->bd_h[i].host_virt_h;
216                         l = ch->bd_h[i].host_virt_l;
217                         q_priv->msg_ch_vaddr[i] = (void *)join_32_bits(h, l);
218                 }
219
220                 rte_bbdev_log(WARNING,
221                         "Queue [%d] already configured, not configuring again",
222                         q_priv->q_id);
223                 return 0;
224         }
225
226         rte_bbdev_log_debug("setting up queue %d", q_priv->q_id);
227
228         /* Call ipc_configure_channel */
229         ret = ipc_queue_configure(q_priv->q_id, ipc_priv, q_priv);
230         if (ret) {
231                 rte_bbdev_log(ERR, "Unable to setup queue (%d) (err=%d)",
232                        q_priv->q_id, ret);
233                 return ret;
234         }
235
236         /* Set queue properties for LA12xx device */
237         switch (q_priv->op_type) {
238         case RTE_BBDEV_OP_LDPC_ENC:
239                 if (priv->num_ldpc_enc_queues >= LA12XX_MAX_LDPC_ENC_QUEUES) {
240                         rte_bbdev_log(ERR,
241                                 "num_ldpc_enc_queues reached max value");
242                         return -1;
243                 }
244                 ch->la12xx_core_id =
245                         rte_cpu_to_be_32(LA12XX_LDPC_ENC_CORE);
246                 ch->feca_blk_id = rte_cpu_to_be_32(priv->num_ldpc_enc_queues++);
247                 break;
248         case RTE_BBDEV_OP_LDPC_DEC:
249                 if (priv->num_ldpc_dec_queues >= LA12XX_MAX_LDPC_DEC_QUEUES) {
250                         rte_bbdev_log(ERR,
251                                 "num_ldpc_dec_queues reached max value");
252                         return -1;
253                 }
254                 ch->la12xx_core_id =
255                         rte_cpu_to_be_32(LA12XX_LDPC_DEC_CORE);
256                 ch->feca_blk_id = rte_cpu_to_be_32(priv->num_ldpc_dec_queues++);
257                 break;
258         default:
259                 rte_bbdev_log(ERR, "Not supported op type\n");
260                 return -1;
261         }
262         ch->op_type = rte_cpu_to_be_32(q_priv->op_type);
263         ch->depth = rte_cpu_to_be_32(q_priv->queue_size);
264
265         /* Store queue config here */
266         q_priv->feca_blk_id = rte_cpu_to_be_32(ch->feca_blk_id);
267         q_priv->feca_blk_id_be32 = ch->feca_blk_id;
268
269         return 0;
270 }
271
272 /* Setup a queue */
273 static int
274 la12xx_queue_setup(struct rte_bbdev *dev, uint16_t q_id,
275                 const struct rte_bbdev_queue_conf *queue_conf)
276 {
277         struct bbdev_la12xx_private *priv = dev->data->dev_private;
278         struct rte_bbdev_queue_data *q_data;
279         struct bbdev_la12xx_q_priv *q_priv;
280         int ret;
281
282         PMD_INIT_FUNC_TRACE();
283
284         /* Move to setup_queues callback */
285         q_data = &dev->data->queues[q_id];
286         q_data->queue_private = rte_zmalloc(NULL,
287                 sizeof(struct bbdev_la12xx_q_priv), 0);
288         if (!q_data->queue_private) {
289                 rte_bbdev_log(ERR, "Memory allocation failed for qpriv");
290                 return -ENOMEM;
291         }
292         q_priv = q_data->queue_private;
293         q_priv->q_id = q_id;
294         q_priv->bbdev_priv = dev->data->dev_private;
295         q_priv->queue_size = queue_conf->queue_size;
296         q_priv->op_type = queue_conf->op_type;
297
298         ret = la12xx_e200_queue_setup(dev, q_priv);
299         if (ret) {
300                 rte_bbdev_log(ERR, "e200_queue_setup failed for qid: %d",
301                                      q_id);
302                 return ret;
303         }
304
305         /* Store queue config here */
306         priv->num_valid_queues++;
307
308         return 0;
309 }
310
311 static int
312 la12xx_start(struct rte_bbdev *dev)
313 {
314         struct bbdev_la12xx_private *priv = dev->data->dev_private;
315         ipc_userspace_t *ipc_priv = priv->ipc_priv;
316         int ready = 0;
317         struct gul_hif *hif_start;
318
319         PMD_INIT_FUNC_TRACE();
320
321         hif_start = (struct gul_hif *)ipc_priv->mhif_start.host_vaddr;
322
323         /* Set Host Read bit */
324         SET_HIF_HOST_RDY(hif_start, HIF_HOST_READY_IPC_APP);
325
326         /* Now wait for modem ready bit */
327         while (!ready)
328                 ready = CHK_HIF_MOD_RDY(hif_start, HIF_MOD_READY_IPC_APP);
329
330         return 0;
331 }
332
333 static const struct rte_bbdev_ops pmd_ops = {
334         .info_get = la12xx_info_get,
335         .queue_setup = la12xx_queue_setup,
336         .queue_release = la12xx_queue_release,
337         .start = la12xx_start
338 };
339 static struct hugepage_info *
340 get_hugepage_info(void)
341 {
342         struct hugepage_info *hp_info;
343         struct rte_memseg *mseg;
344
345         PMD_INIT_FUNC_TRACE();
346
347         /* TODO - find a better way */
348         hp_info = rte_malloc(NULL, sizeof(struct hugepage_info), 0);
349         if (!hp_info) {
350                 rte_bbdev_log(ERR, "Unable to allocate on local heap");
351                 return NULL;
352         }
353
354         mseg = rte_mem_virt2memseg(hp_info, NULL);
355         hp_info->vaddr = mseg->addr;
356         hp_info->paddr = rte_mem_virt2phy(mseg->addr);
357         hp_info->len = mseg->len;
358
359         return hp_info;
360 }
361
362 static int
363 open_ipc_dev(int modem_id)
364 {
365         char dev_initials[16], dev_path[PATH_MAX];
366         struct dirent *entry;
367         int dev_ipc = 0;
368         DIR *dir;
369
370         dir = opendir("/dev/");
371         if (!dir) {
372                 rte_bbdev_log(ERR, "Unable to open /dev/");
373                 return -1;
374         }
375
376         sprintf(dev_initials, "gulipcgul%d", modem_id);
377
378         while ((entry = readdir(dir)) != NULL) {
379                 if (!strncmp(dev_initials, entry->d_name,
380                     sizeof(dev_initials) - 1))
381                         break;
382         }
383
384         if (!entry) {
385                 rte_bbdev_log(ERR, "Error: No gulipcgul%d device", modem_id);
386                 return -1;
387         }
388
389         sprintf(dev_path, "/dev/%s", entry->d_name);
390         dev_ipc = open(dev_path, O_RDWR);
391         if (dev_ipc  < 0) {
392                 rte_bbdev_log(ERR, "Error: Cannot open %s", dev_path);
393                 return -errno;
394         }
395
396         return dev_ipc;
397 }
398
399 static int
400 setup_la12xx_dev(struct rte_bbdev *dev)
401 {
402         struct bbdev_la12xx_private *priv = dev->data->dev_private;
403         ipc_userspace_t *ipc_priv = priv->ipc_priv;
404         struct hugepage_info *hp = NULL;
405         ipc_channel_us_t *ipc_priv_ch = NULL;
406         int dev_ipc = 0, dev_mem = 0, i;
407         ipc_metadata_t *ipc_md;
408         struct gul_hif *mhif;
409         uint32_t phy_align = 0;
410         int ret;
411
412         PMD_INIT_FUNC_TRACE();
413
414         if (!ipc_priv) {
415                 /* TODO - get a better way */
416                 /* Get the hugepage info against it */
417                 hp = get_hugepage_info();
418                 if (!hp) {
419                         rte_bbdev_log(ERR, "Unable to get hugepage info");
420                         ret = -ENOMEM;
421                         goto err;
422                 }
423
424                 rte_bbdev_log_debug("0x%" PRIx64 " %p 0x%" PRIx64,
425                                 hp->paddr, hp->vaddr, hp->len);
426
427                 ipc_priv = rte_zmalloc(0, sizeof(ipc_userspace_t), 0);
428                 if (ipc_priv == NULL) {
429                         rte_bbdev_log(ERR,
430                                 "Unable to allocate memory for ipc priv");
431                         ret = -ENOMEM;
432                         goto err;
433                 }
434
435                 for (i = 0; i < IPC_MAX_CHANNEL_COUNT; i++) {
436                         ipc_priv_ch = rte_zmalloc(0,
437                                 sizeof(ipc_channel_us_t), 0);
438                         if (ipc_priv_ch == NULL) {
439                                 rte_bbdev_log(ERR,
440                                         "Unable to allocate memory for channels");
441                                 ret = -ENOMEM;
442                         }
443                         ipc_priv->channels[i] = ipc_priv_ch;
444                 }
445
446                 dev_mem = open("/dev/mem", O_RDWR);
447                 if (dev_mem < 0) {
448                         rte_bbdev_log(ERR, "Error: Cannot open /dev/mem");
449                         ret = -errno;
450                         goto err;
451                 }
452
453                 ipc_priv->instance_id = 0;
454                 ipc_priv->dev_mem = dev_mem;
455
456                 rte_bbdev_log_debug("hugepg input 0x%" PRIx64 "%p 0x%" PRIx64,
457                         hp->paddr, hp->vaddr, hp->len);
458
459                 ipc_priv->sys_map.hugepg_start.host_phys = hp->paddr;
460                 ipc_priv->sys_map.hugepg_start.size = hp->len;
461
462                 ipc_priv->hugepg_start.host_phys = hp->paddr;
463                 ipc_priv->hugepg_start.host_vaddr = hp->vaddr;
464                 ipc_priv->hugepg_start.size = hp->len;
465
466                 rte_free(hp);
467         }
468
469         dev_ipc = open_ipc_dev(priv->modem_id);
470         if (dev_ipc < 0) {
471                 rte_bbdev_log(ERR, "Error: open_ipc_dev failed");
472                 goto err;
473         }
474         ipc_priv->dev_ipc = dev_ipc;
475
476         ret = ioctl(ipc_priv->dev_ipc, IOCTL_GUL_IPC_GET_SYS_MAP,
477                     &ipc_priv->sys_map);
478         if (ret) {
479                 rte_bbdev_log(ERR,
480                         "IOCTL_GUL_IPC_GET_SYS_MAP ioctl failed");
481                 goto err;
482         }
483
484         phy_align = (ipc_priv->sys_map.mhif_start.host_phys % 0x1000);
485         ipc_priv->mhif_start.host_vaddr =
486                 mmap(0, ipc_priv->sys_map.mhif_start.size + phy_align,
487                      (PROT_READ | PROT_WRITE), MAP_SHARED, ipc_priv->dev_mem,
488                      (ipc_priv->sys_map.mhif_start.host_phys - phy_align));
489         if (ipc_priv->mhif_start.host_vaddr == MAP_FAILED) {
490                 rte_bbdev_log(ERR, "MAP failed:");
491                 ret = -errno;
492                 goto err;
493         }
494
495         ipc_priv->mhif_start.host_vaddr = (void *) ((uintptr_t)
496                 (ipc_priv->mhif_start.host_vaddr) + phy_align);
497
498         phy_align = (ipc_priv->sys_map.peb_start.host_phys % 0x1000);
499         ipc_priv->peb_start.host_vaddr =
500                 mmap(0, ipc_priv->sys_map.peb_start.size + phy_align,
501                      (PROT_READ | PROT_WRITE), MAP_SHARED, ipc_priv->dev_mem,
502                      (ipc_priv->sys_map.peb_start.host_phys - phy_align));
503         if (ipc_priv->peb_start.host_vaddr == MAP_FAILED) {
504                 rte_bbdev_log(ERR, "MAP failed:");
505                 ret = -errno;
506                 goto err;
507         }
508
509         ipc_priv->peb_start.host_vaddr = (void *)((uintptr_t)
510                 (ipc_priv->peb_start.host_vaddr) + phy_align);
511
512         phy_align = (ipc_priv->sys_map.modem_ccsrbar.host_phys % 0x1000);
513         ipc_priv->modem_ccsrbar.host_vaddr =
514                 mmap(0, ipc_priv->sys_map.modem_ccsrbar.size + phy_align,
515                      (PROT_READ | PROT_WRITE), MAP_SHARED, ipc_priv->dev_mem,
516                      (ipc_priv->sys_map.modem_ccsrbar.host_phys - phy_align));
517         if (ipc_priv->modem_ccsrbar.host_vaddr == MAP_FAILED) {
518                 rte_bbdev_log(ERR, "MAP failed:");
519                 ret = -errno;
520                 goto err;
521         }
522
523         ipc_priv->modem_ccsrbar.host_vaddr = (void *)((uintptr_t)
524                 (ipc_priv->modem_ccsrbar.host_vaddr) + phy_align);
525
526         ipc_priv->hugepg_start.modem_phys =
527                 ipc_priv->sys_map.hugepg_start.modem_phys;
528
529         ipc_priv->mhif_start.host_phys =
530                 ipc_priv->sys_map.mhif_start.host_phys;
531         ipc_priv->mhif_start.size = ipc_priv->sys_map.mhif_start.size;
532         ipc_priv->peb_start.host_phys = ipc_priv->sys_map.peb_start.host_phys;
533         ipc_priv->peb_start.size = ipc_priv->sys_map.peb_start.size;
534
535         rte_bbdev_log(INFO, "peb 0x%" PRIx64 "%p 0x%" PRIx32,
536                         ipc_priv->peb_start.host_phys,
537                         ipc_priv->peb_start.host_vaddr,
538                         ipc_priv->peb_start.size);
539         rte_bbdev_log(INFO, "hugepg 0x%" PRIx64 "%p 0x%" PRIx32,
540                         ipc_priv->hugepg_start.host_phys,
541                         ipc_priv->hugepg_start.host_vaddr,
542                         ipc_priv->hugepg_start.size);
543         rte_bbdev_log(INFO, "mhif 0x%" PRIx64 "%p 0x%" PRIx32,
544                         ipc_priv->mhif_start.host_phys,
545                         ipc_priv->mhif_start.host_vaddr,
546                         ipc_priv->mhif_start.size);
547         mhif = (struct gul_hif *)ipc_priv->mhif_start.host_vaddr;
548
549         /* offset is from start of PEB */
550         ipc_md = (ipc_metadata_t *)((uintptr_t)ipc_priv->peb_start.host_vaddr +
551                         mhif->ipc_regs.ipc_mdata_offset);
552
553         if (sizeof(ipc_metadata_t) != mhif->ipc_regs.ipc_mdata_size) {
554                 rte_bbdev_log(ERR,
555                         "ipc_metadata_t =0x%" PRIx64
556                         ", mhif->ipc_regs.ipc_mdata_size=0x%" PRIx32,
557                         (uint64_t)(sizeof(ipc_metadata_t)),
558                         mhif->ipc_regs.ipc_mdata_size);
559                 rte_bbdev_log(ERR, "--> mhif->ipc_regs.ipc_mdata_offset= 0x%"
560                         PRIx32, mhif->ipc_regs.ipc_mdata_offset);
561                 rte_bbdev_log(ERR, "gul_hif size=0x%" PRIx64,
562                         (uint64_t)(sizeof(struct gul_hif)));
563                 return IPC_MD_SZ_MISS_MATCH;
564         }
565
566         ipc_priv->instance = (ipc_instance_t *)
567                 (&ipc_md->instance_list[ipc_priv->instance_id]);
568
569         rte_bbdev_log_debug("finish host init");
570
571         priv->ipc_priv = ipc_priv;
572
573         return 0;
574
575 err:
576         rte_free(hp);
577         rte_free(ipc_priv);
578         rte_free(ipc_priv_ch);
579         if (dev_mem)
580                 close(dev_mem);
581         if (dev_ipc)
582                 close(dev_ipc);
583
584         return ret;
585 }
586
587 static inline int
588 parse_u16_arg(const char *key, const char *value, void *extra_args)
589 {
590         uint16_t *u16 = extra_args;
591
592         uint64_t result;
593         if ((value == NULL) || (extra_args == NULL))
594                 return -EINVAL;
595         errno = 0;
596         result = strtoul(value, NULL, 0);
597         if ((result >= (1 << 16)) || (errno != 0)) {
598                 rte_bbdev_log(ERR, "Invalid value %" PRIu64 " for %s",
599                               result, key);
600                 return -ERANGE;
601         }
602         *u16 = (uint16_t)result;
603         return 0;
604 }
605
606 /* Parse integer from integer argument */
607 static int
608 parse_integer_arg(const char *key __rte_unused,
609                 const char *value, void *extra_args)
610 {
611         int i;
612         char *end;
613
614         errno = 0;
615
616         i = strtol(value, &end, 10);
617         if (*end != 0 || errno != 0 || i < 0 || i > LA12XX_MAX_MODEM) {
618                 rte_bbdev_log(ERR, "Supported Port IDS are 0 to %d",
619                         LA12XX_MAX_MODEM - 1);
620                 return -EINVAL;
621         }
622
623         *((uint32_t *)extra_args) = i;
624
625         return 0;
626 }
627
628 /* Parse parameters used to create device */
629 static int
630 parse_bbdev_la12xx_params(struct bbdev_la12xx_params *params,
631                 const char *input_args)
632 {
633         struct rte_kvargs *kvlist = NULL;
634         int ret = 0;
635
636         if (params == NULL)
637                 return -EINVAL;
638         if (input_args) {
639                 kvlist = rte_kvargs_parse(input_args,
640                                 bbdev_la12xx_valid_params);
641                 if (kvlist == NULL)
642                         return -EFAULT;
643
644                 ret = rte_kvargs_process(kvlist, bbdev_la12xx_valid_params[0],
645                                         &parse_u16_arg, &params->queues_num);
646                 if (ret < 0)
647                         goto exit;
648
649                 ret = rte_kvargs_process(kvlist,
650                                         bbdev_la12xx_valid_params[1],
651                                         &parse_integer_arg,
652                                         &params->modem_id);
653
654                 if (params->modem_id >= LA12XX_MAX_MODEM) {
655                         rte_bbdev_log(ERR, "Invalid modem id, must be < %u",
656                                         LA12XX_MAX_MODEM);
657                         goto exit;
658                 }
659         }
660
661 exit:
662         if (kvlist)
663                 rte_kvargs_free(kvlist);
664         return ret;
665 }
666
667 /* Create device */
668 static int
669 la12xx_bbdev_create(struct rte_vdev_device *vdev,
670                 struct bbdev_la12xx_params *init_params)
671 {
672         struct rte_bbdev *bbdev;
673         const char *name = rte_vdev_device_name(vdev);
674         struct bbdev_la12xx_private *priv;
675         int ret;
676
677         PMD_INIT_FUNC_TRACE();
678
679         bbdev = rte_bbdev_allocate(name);
680         if (bbdev == NULL)
681                 return -ENODEV;
682
683         bbdev->data->dev_private = rte_zmalloc(name,
684                         sizeof(struct bbdev_la12xx_private),
685                         RTE_CACHE_LINE_SIZE);
686         if (bbdev->data->dev_private == NULL) {
687                 rte_bbdev_release(bbdev);
688                 return -ENOMEM;
689         }
690
691         priv = bbdev->data->dev_private;
692         priv->modem_id = init_params->modem_id;
693         /* if modem id is not configured */
694         if (priv->modem_id == -1)
695                 priv->modem_id = bbdev->data->dev_id;
696
697         /* Reset Global variables */
698         priv->num_ldpc_enc_queues = 0;
699         priv->num_ldpc_dec_queues = 0;
700         priv->num_valid_queues = 0;
701         priv->max_nb_queues = init_params->queues_num;
702
703         rte_bbdev_log(INFO, "Setting Up %s: DevId=%d, ModemId=%d",
704                                 name, bbdev->data->dev_id, priv->modem_id);
705         ret = setup_la12xx_dev(bbdev);
706         if (ret) {
707                 rte_bbdev_log(ERR, "IPC Setup failed for %s", name);
708                 rte_free(bbdev->data->dev_private);
709                 return ret;
710         }
711         bbdev->dev_ops = &pmd_ops;
712         bbdev->device = &vdev->device;
713         bbdev->data->socket_id = 0;
714         bbdev->intr_handle = NULL;
715
716         /* register rx/tx burst functions for data path */
717         bbdev->dequeue_enc_ops = NULL;
718         bbdev->dequeue_dec_ops = NULL;
719         bbdev->enqueue_enc_ops = NULL;
720         bbdev->enqueue_dec_ops = NULL;
721
722         return 0;
723 }
724
725 /* Initialise device */
726 static int
727 la12xx_bbdev_probe(struct rte_vdev_device *vdev)
728 {
729         struct bbdev_la12xx_params init_params = {
730                 8, -1,
731         };
732         const char *name;
733         const char *input_args;
734
735         PMD_INIT_FUNC_TRACE();
736
737         if (vdev == NULL)
738                 return -EINVAL;
739
740         name = rte_vdev_device_name(vdev);
741         if (name == NULL)
742                 return -EINVAL;
743
744         input_args = rte_vdev_device_args(vdev);
745         parse_bbdev_la12xx_params(&init_params, input_args);
746
747         return la12xx_bbdev_create(vdev, &init_params);
748 }
749
750 /* Uninitialise device */
751 static int
752 la12xx_bbdev_remove(struct rte_vdev_device *vdev)
753 {
754         struct rte_bbdev *bbdev;
755         const char *name;
756
757         PMD_INIT_FUNC_TRACE();
758
759         if (vdev == NULL)
760                 return -EINVAL;
761
762         name = rte_vdev_device_name(vdev);
763         if (name == NULL)
764                 return -EINVAL;
765
766         bbdev = rte_bbdev_get_named_dev(name);
767         if (bbdev == NULL)
768                 return -EINVAL;
769
770         rte_free(bbdev->data->dev_private);
771
772         return rte_bbdev_release(bbdev);
773 }
774
775 static struct rte_vdev_driver bbdev_la12xx_pmd_drv = {
776         .probe = la12xx_bbdev_probe,
777         .remove = la12xx_bbdev_remove
778 };
779
780 RTE_PMD_REGISTER_VDEV(DRIVER_NAME, bbdev_la12xx_pmd_drv);
781 RTE_PMD_REGISTER_PARAM_STRING(DRIVER_NAME,
782         LA12XX_MAX_NB_QUEUES_ARG"=<int>"
783         LA12XX_VDEV_MODEM_ID_ARG "=<int> ");
784 RTE_LOG_REGISTER_DEFAULT(bbdev_la12xx_logtype, NOTICE);