net/pfe: introduce basic functions
[dpdk.git] / drivers / net / pfe / pfe_ethdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2019 NXP
3  */
4
5 #include <rte_kvargs.h>
6 #include <rte_ethdev_vdev.h>
7 #include <rte_bus_vdev.h>
8 #include <dpaa_of.h>
9
10 #include "pfe_mod.h"
11
12 #define PFE_MAX_MACS 1 /*we can support upto 4 MACs per IF*/
13 #define PFE_VDEV_GEM_ID_ARG     "intf"
14
15 struct pfe_vdev_init_params {
16         int8_t  gem_id;
17 };
18 static struct pfe *g_pfe;
19
20 /* TODO: make pfe_svr a runtime option.
21  * Driver should be able to get the SVR
22  * information from HW.
23  */
24 unsigned int pfe_svr = SVR_LS1012A_REV1;
25
26 static void
27 pfe_soc_version_get(void)
28 {
29         FILE *svr_file = NULL;
30         unsigned int svr_ver = 0;
31
32         svr_file = fopen(PFE_SOC_ID_FILE, "r");
33         if (!svr_file)
34                 return; /* Not supported on this infra */
35
36         if (fscanf(svr_file, "svr:%x", &svr_ver) > 0)
37                 pfe_svr = svr_ver;
38         else
39                 printf("Unable to read SoC device");
40
41         fclose(svr_file);
42 }
43
44 static int
45 pfe_eth_open_cdev(struct pfe_eth_priv_s *priv)
46 {
47         int pfe_cdev_fd;
48
49         if (priv == NULL)
50                 return -1;
51
52         pfe_cdev_fd = open(PFE_CDEV_PATH, O_RDONLY);
53         if (pfe_cdev_fd < 0) {
54                 priv->link_fd = PFE_CDEV_INVALID_FD;
55                 return -1;
56         }
57
58         priv->link_fd = pfe_cdev_fd;
59
60         return 0;
61 }
62
63 static void
64 pfe_eth_close_cdev(struct pfe_eth_priv_s *priv)
65 {
66         if (priv == NULL)
67                 return;
68
69         if (priv->link_fd != PFE_CDEV_INVALID_FD) {
70                 close(priv->link_fd);
71                 priv->link_fd = PFE_CDEV_INVALID_FD;
72         }
73 }
74
75 static void
76 pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe)
77 {
78         /* Close the device file for link status */
79         pfe_eth_close_cdev(dev->data->dev_private);
80
81         rte_free(dev->data->mac_addrs);
82         rte_eth_dev_release_port(dev);
83         pfe->nb_devs--;
84 }
85
86 static int
87 pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
88 {
89         struct rte_eth_dev *eth_dev = NULL;
90         struct pfe_eth_priv_s *priv = NULL;
91         int err;
92
93         eth_dev = rte_eth_vdev_allocate(vdev, sizeof(*priv));
94         if (eth_dev == NULL)
95                 return -ENOMEM;
96
97         priv = eth_dev->data->dev_private;
98         priv->ndev = eth_dev;
99         priv->pfe = pfe;
100
101         pfe->eth.eth_priv[id] = priv;
102
103 #define HIF_GEMAC_TMUQ_BASE     6
104         priv->low_tmu_q = HIF_GEMAC_TMUQ_BASE + (id * 2);
105         priv->high_tmu_q = priv->low_tmu_q + 1;
106
107         rte_spinlock_init(&priv->lock);
108
109         /* Copy the station address into the dev structure, */
110         eth_dev->data->mac_addrs = rte_zmalloc("mac_addr",
111                         ETHER_ADDR_LEN * PFE_MAX_MACS, 0);
112         if (eth_dev->data->mac_addrs == NULL) {
113                 err = -ENOMEM;
114                 goto err0;
115         }
116
117         eth_dev->data->mtu = 1500;
118
119         eth_dev->data->nb_rx_queues = 1;
120         eth_dev->data->nb_tx_queues = 1;
121
122         /* For link status, open the PFE CDEV; Error from this function
123          * is silently ignored; In case of error, the link status will not
124          * be available.
125          */
126         pfe_eth_open_cdev(priv);
127         rte_eth_dev_probing_finish(eth_dev);
128
129         return 0;
130 err0:
131         rte_eth_dev_release_port(eth_dev);
132         return err;
133 }
134
135 /* Parse integer from integer argument */
136 static int
137 parse_integer_arg(const char *key __rte_unused,
138                 const char *value, void *extra_args)
139 {
140         int i;
141         char *end;
142         errno = 0;
143
144         i = strtol(value, &end, 10);
145         if (*end != 0 || errno != 0 || i < 0 || i > 1)
146                 return -EINVAL;
147
148         *((uint32_t *)extra_args) = i;
149
150         return 0;
151 }
152
153 static int
154 pfe_parse_vdev_init_params(struct pfe_vdev_init_params *params,
155                            struct rte_vdev_device *dev)
156 {
157         struct rte_kvargs *kvlist = NULL;
158         int ret = 0;
159
160         static const char * const pfe_vdev_valid_params[] = {
161                 PFE_VDEV_GEM_ID_ARG,
162                 NULL
163         };
164
165         const char *input_args = rte_vdev_device_args(dev);
166
167         if (!input_args)
168                 return -1;
169
170         kvlist = rte_kvargs_parse(input_args, pfe_vdev_valid_params);
171         if (kvlist == NULL)
172                 return -1;
173
174         ret = rte_kvargs_process(kvlist,
175                                 PFE_VDEV_GEM_ID_ARG,
176                                 &parse_integer_arg,
177                                 &params->gem_id);
178         rte_kvargs_free(kvlist);
179         return ret;
180 }
181
182 static int
183 pmd_pfe_probe(struct rte_vdev_device *vdev)
184 {
185         const u32 *prop;
186         const struct device_node *np;
187         const char *name;
188         const uint32_t *addr;
189         uint64_t cbus_addr, ddr_size, cbus_size;
190         int rc = -1, fd = -1, gem_id;
191         unsigned int interface_count = 0;
192         size_t size = 0;
193         struct pfe_vdev_init_params init_params = {
194                 .gem_id = -1
195         };
196
197         name = rte_vdev_device_name(vdev);
198         rc = pfe_parse_vdev_init_params(&init_params, vdev);
199         if (rc < 0)
200                 return -EINVAL;
201
202         if (g_pfe) {
203                 if (g_pfe->nb_devs >= g_pfe->max_intf)
204                         return -EINVAL;
205
206                 goto eth_init;
207         }
208
209         g_pfe = rte_zmalloc(NULL, sizeof(*g_pfe), RTE_CACHE_LINE_SIZE);
210         if (g_pfe == NULL)
211                 return  -EINVAL;
212
213         /* Load the device-tree driver */
214         rc = of_init();
215         if (rc)
216                 goto err;
217
218         np = of_find_compatible_node(NULL, NULL, "fsl,pfe");
219         if (!np) {
220                 rc = -EINVAL;
221                 goto err;
222         }
223
224         addr = of_get_address(np, 0, &cbus_size, NULL);
225         if (!addr)
226                 goto err;
227
228         cbus_addr = of_translate_address(np, addr);
229         if (!cbus_addr)
230                 goto err;
231
232
233         addr = of_get_address(np, 1, &ddr_size, NULL);
234         if (!addr)
235                 goto err;
236
237         g_pfe->ddr_phys_baseaddr = of_translate_address(np, addr);
238         if (!g_pfe->ddr_phys_baseaddr)
239                 goto err;
240
241         g_pfe->ddr_size = ddr_size;
242         g_pfe->cbus_size = cbus_size;
243
244         fd = open("/dev/mem", O_RDWR);
245         g_pfe->cbus_baseaddr = mmap(NULL, cbus_size, PROT_READ | PROT_WRITE,
246                                         MAP_SHARED, fd, cbus_addr);
247         close(fd);
248         if (g_pfe->cbus_baseaddr == MAP_FAILED) {
249                 rc = -EINVAL;
250                 goto err;
251         }
252
253         /* Read interface count */
254         prop = of_get_property(np, "fsl,pfe-num-interfaces", &size);
255         if (!prop) {
256                 rc = -ENXIO;
257                 goto err_prop;
258         }
259
260         interface_count = rte_be_to_cpu_32((unsigned int)*prop);
261         if (interface_count <= 0) {
262                 rc = -ENXIO;
263                 goto err_prop;
264         }
265         g_pfe->max_intf  = interface_count;
266         pfe_soc_version_get();
267 eth_init:
268         if (init_params.gem_id < 0)
269                 gem_id = g_pfe->nb_devs;
270         else
271                 gem_id = init_params.gem_id;
272
273         RTE_LOG(INFO, PMD, "Init pmd_pfe for %s gem-id %d(given =%d)\n",
274                 name, gem_id, init_params.gem_id);
275
276         rc = pfe_eth_init(vdev, g_pfe, gem_id);
277         if (rc < 0)
278                 goto err_eth;
279         else
280                 g_pfe->nb_devs++;
281
282         return 0;
283
284 err_eth:
285 err_prop:
286         munmap(g_pfe->cbus_baseaddr, cbus_size);
287 err:
288         rte_free(g_pfe);
289         return rc;
290 }
291
292 static int
293 pmd_pfe_remove(struct rte_vdev_device *vdev)
294 {
295         const char *name;
296         struct rte_eth_dev *eth_dev = NULL;
297
298         name = rte_vdev_device_name(vdev);
299         if (name == NULL)
300                 return -EINVAL;
301
302         if (!g_pfe)
303                 return 0;
304
305         eth_dev = rte_eth_dev_allocated(name);
306         if (eth_dev == NULL)
307                 return -ENODEV;
308
309         pfe_eth_exit(eth_dev, g_pfe);
310         munmap(g_pfe->cbus_baseaddr, g_pfe->cbus_size);
311
312         return 0;
313 }
314
315 static
316 struct rte_vdev_driver pmd_pfe_drv = {
317         .probe = pmd_pfe_probe,
318         .remove = pmd_pfe_remove,
319 };
320
321 RTE_PMD_REGISTER_VDEV(PFE_NAME_PMD, pmd_pfe_drv);
322 RTE_PMD_REGISTER_PARAM_STRING(PFE_NAME_PMD, PFE_VDEV_GEM_ID_ARG "=<int> ");