baseband/la12xx: support multiple modems
[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
7 #include <rte_common.h>
8 #include <rte_bus_vdev.h>
9 #include <rte_malloc.h>
10 #include <rte_ring.h>
11 #include <rte_kvargs.h>
12
13 #include <rte_bbdev.h>
14 #include <rte_bbdev_pmd.h>
15
16 #include <bbdev_la12xx_pmd_logs.h>
17 #include <bbdev_la12xx_ipc.h>
18 #include <bbdev_la12xx.h>
19
20 #define DRIVER_NAME baseband_la12xx
21
22 /*  Initialisation params structure that can be used by LA12xx BBDEV driver */
23 struct bbdev_la12xx_params {
24         uint8_t queues_num; /*< LA12xx BBDEV queues number */
25         int8_t modem_id; /*< LA12xx modem instance id */
26 };
27
28 #define LA12XX_MAX_NB_QUEUES_ARG        "max_nb_queues"
29 #define LA12XX_VDEV_MODEM_ID_ARG        "modem"
30 #define LA12XX_MAX_MODEM 4
31
32 static const char * const bbdev_la12xx_valid_params[] = {
33         LA12XX_MAX_NB_QUEUES_ARG,
34         LA12XX_VDEV_MODEM_ID_ARG,
35 };
36
37 static inline int
38 parse_u16_arg(const char *key, const char *value, void *extra_args)
39 {
40         uint16_t *u16 = extra_args;
41
42         uint64_t result;
43         if ((value == NULL) || (extra_args == NULL))
44                 return -EINVAL;
45         errno = 0;
46         result = strtoul(value, NULL, 0);
47         if ((result >= (1 << 16)) || (errno != 0)) {
48                 rte_bbdev_log(ERR, "Invalid value %" PRIu64 " for %s",
49                               result, key);
50                 return -ERANGE;
51         }
52         *u16 = (uint16_t)result;
53         return 0;
54 }
55
56 /* Parse integer from integer argument */
57 static int
58 parse_integer_arg(const char *key __rte_unused,
59                 const char *value, void *extra_args)
60 {
61         int i;
62         char *end;
63
64         errno = 0;
65
66         i = strtol(value, &end, 10);
67         if (*end != 0 || errno != 0 || i < 0 || i > LA12XX_MAX_MODEM) {
68                 rte_bbdev_log(ERR, "Supported Port IDS are 0 to %d",
69                         LA12XX_MAX_MODEM - 1);
70                 return -EINVAL;
71         }
72
73         *((uint32_t *)extra_args) = i;
74
75         return 0;
76 }
77
78 /* Parse parameters used to create device */
79 static int
80 parse_bbdev_la12xx_params(struct bbdev_la12xx_params *params,
81                 const char *input_args)
82 {
83         struct rte_kvargs *kvlist = NULL;
84         int ret = 0;
85
86         if (params == NULL)
87                 return -EINVAL;
88         if (input_args) {
89                 kvlist = rte_kvargs_parse(input_args,
90                                 bbdev_la12xx_valid_params);
91                 if (kvlist == NULL)
92                         return -EFAULT;
93
94                 ret = rte_kvargs_process(kvlist, bbdev_la12xx_valid_params[0],
95                                         &parse_u16_arg, &params->queues_num);
96                 if (ret < 0)
97                         goto exit;
98
99                 ret = rte_kvargs_process(kvlist,
100                                         bbdev_la12xx_valid_params[1],
101                                         &parse_integer_arg,
102                                         &params->modem_id);
103
104                 if (params->modem_id >= LA12XX_MAX_MODEM) {
105                         rte_bbdev_log(ERR, "Invalid modem id, must be < %u",
106                                         LA12XX_MAX_MODEM);
107                         goto exit;
108                 }
109         }
110
111 exit:
112         if (kvlist)
113                 rte_kvargs_free(kvlist);
114         return ret;
115 }
116
117 /* Create device */
118 static int
119 la12xx_bbdev_create(struct rte_vdev_device *vdev,
120                 struct bbdev_la12xx_params *init_params)
121 {
122         struct rte_bbdev *bbdev;
123         const char *name = rte_vdev_device_name(vdev);
124         struct bbdev_la12xx_private *priv;
125
126         PMD_INIT_FUNC_TRACE();
127
128         bbdev = rte_bbdev_allocate(name);
129         if (bbdev == NULL)
130                 return -ENODEV;
131
132         bbdev->data->dev_private = rte_zmalloc(name,
133                         sizeof(struct bbdev_la12xx_private),
134                         RTE_CACHE_LINE_SIZE);
135         if (bbdev->data->dev_private == NULL) {
136                 rte_bbdev_release(bbdev);
137                 return -ENOMEM;
138         }
139
140         priv = bbdev->data->dev_private;
141         priv->modem_id = init_params->modem_id;
142         /* if modem id is not configured */
143         if (priv->modem_id == -1)
144                 priv->modem_id = bbdev->data->dev_id;
145
146         /* Reset Global variables */
147         priv->num_ldpc_enc_queues = 0;
148         priv->num_ldpc_dec_queues = 0;
149         priv->num_valid_queues = 0;
150         priv->max_nb_queues = init_params->queues_num;
151
152         rte_bbdev_log(INFO, "Setting Up %s: DevId=%d, ModemId=%d",
153                                 name, bbdev->data->dev_id, priv->modem_id);
154         bbdev->dev_ops = NULL;
155         bbdev->device = &vdev->device;
156         bbdev->data->socket_id = 0;
157         bbdev->intr_handle = NULL;
158
159         /* register rx/tx burst functions for data path */
160         bbdev->dequeue_enc_ops = NULL;
161         bbdev->dequeue_dec_ops = NULL;
162         bbdev->enqueue_enc_ops = NULL;
163         bbdev->enqueue_dec_ops = NULL;
164
165         return 0;
166 }
167
168 /* Initialise device */
169 static int
170 la12xx_bbdev_probe(struct rte_vdev_device *vdev)
171 {
172         struct bbdev_la12xx_params init_params = {
173                 8, -1,
174         };
175         const char *name;
176         const char *input_args;
177
178         PMD_INIT_FUNC_TRACE();
179
180         if (vdev == NULL)
181                 return -EINVAL;
182
183         name = rte_vdev_device_name(vdev);
184         if (name == NULL)
185                 return -EINVAL;
186
187         input_args = rte_vdev_device_args(vdev);
188         parse_bbdev_la12xx_params(&init_params, input_args);
189
190         return la12xx_bbdev_create(vdev, &init_params);
191 }
192
193 /* Uninitialise device */
194 static int
195 la12xx_bbdev_remove(struct rte_vdev_device *vdev)
196 {
197         struct rte_bbdev *bbdev;
198         const char *name;
199
200         PMD_INIT_FUNC_TRACE();
201
202         if (vdev == NULL)
203                 return -EINVAL;
204
205         name = rte_vdev_device_name(vdev);
206         if (name == NULL)
207                 return -EINVAL;
208
209         bbdev = rte_bbdev_get_named_dev(name);
210         if (bbdev == NULL)
211                 return -EINVAL;
212
213         rte_free(bbdev->data->dev_private);
214
215         return rte_bbdev_release(bbdev);
216 }
217
218 static struct rte_vdev_driver bbdev_la12xx_pmd_drv = {
219         .probe = la12xx_bbdev_probe,
220         .remove = la12xx_bbdev_remove
221 };
222
223 RTE_PMD_REGISTER_VDEV(DRIVER_NAME, bbdev_la12xx_pmd_drv);
224 RTE_PMD_REGISTER_PARAM_STRING(DRIVER_NAME,
225         LA12XX_MAX_NB_QUEUES_ARG"=<int>"
226         LA12XX_VDEV_MODEM_ID_ARG "=<int> ");
227 RTE_LOG_REGISTER_DEFAULT(bbdev_la12xx_logtype, NOTICE);