eal: use SPDX tags in 6WIND copyrighted files
[dpdk.git] / lib / librte_eal / common / eal_common_dev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright(c) 2014 6WIND S.A.
4  */
5
6 #include <stdio.h>
7 #include <string.h>
8 #include <inttypes.h>
9 #include <sys/queue.h>
10
11 #include <rte_compat.h>
12 #include <rte_bus.h>
13 #include <rte_dev.h>
14 #include <rte_devargs.h>
15 #include <rte_debug.h>
16 #include <rte_log.h>
17
18 #include "eal_private.h"
19
20 static int cmp_detached_dev_name(const struct rte_device *dev,
21         const void *_name)
22 {
23         const char *name = _name;
24
25         /* skip attached devices */
26         if (dev->driver != NULL)
27                 return 1;
28
29         return strcmp(dev->name, name);
30 }
31
32 static int cmp_dev_name(const struct rte_device *dev, const void *_name)
33 {
34         const char *name = _name;
35
36         return strcmp(dev->name, name);
37 }
38
39 int rte_eal_dev_attach(const char *name, const char *devargs)
40 {
41         struct rte_bus *bus;
42
43         if (name == NULL || devargs == NULL) {
44                 RTE_LOG(ERR, EAL, "Invalid device or arguments provided\n");
45                 return -EINVAL;
46         }
47
48         bus = rte_bus_find_by_device_name(name);
49         if (bus == NULL) {
50                 RTE_LOG(ERR, EAL, "Unable to find a bus for the device '%s'\n",
51                         name);
52                 return -EINVAL;
53         }
54         if (strcmp(bus->name, "pci") == 0 || strcmp(bus->name, "vdev") == 0)
55                 return rte_eal_hotplug_add(bus->name, name, devargs);
56
57         RTE_LOG(ERR, EAL,
58                 "Device attach is only supported for PCI and vdev devices.\n");
59
60         return -ENOTSUP;
61 }
62
63 int rte_eal_dev_detach(struct rte_device *dev)
64 {
65         struct rte_bus *bus;
66         int ret;
67
68         if (dev == NULL) {
69                 RTE_LOG(ERR, EAL, "Invalid device provided.\n");
70                 return -EINVAL;
71         }
72
73         bus = rte_bus_find_by_device(dev);
74         if (bus == NULL) {
75                 RTE_LOG(ERR, EAL, "Cannot find bus for device (%s)\n",
76                         dev->name);
77                 return -EINVAL;
78         }
79
80         if (bus->unplug == NULL) {
81                 RTE_LOG(ERR, EAL, "Bus function not supported\n");
82                 return -ENOTSUP;
83         }
84
85         ret = bus->unplug(dev);
86         if (ret)
87                 RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
88                         dev->name);
89         return ret;
90 }
91
92 static char *
93 full_dev_name(const char *bus, const char *dev, const char *args)
94 {
95         char *name;
96         size_t len;
97
98         len = snprintf(NULL, 0, "%s:%s,%s", bus, dev, args) + 1;
99         name = calloc(1, len);
100         if (name == NULL) {
101                 RTE_LOG(ERR, EAL, "Could not allocate full device name\n");
102                 return NULL;
103         }
104         snprintf(name, len, "%s:%s,%s", bus, dev, args);
105         return name;
106 }
107
108 int __rte_experimental rte_eal_hotplug_add(const char *busname, const char *devname,
109                         const char *devargs)
110 {
111         struct rte_bus *bus;
112         struct rte_device *dev;
113         struct rte_devargs *da;
114         char *name;
115         int ret;
116
117         bus = rte_bus_find_by_name(busname);
118         if (bus == NULL) {
119                 RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname);
120                 return -ENOENT;
121         }
122
123         if (bus->plug == NULL) {
124                 RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n",
125                         bus->name);
126                 return -ENOTSUP;
127         }
128
129         name = full_dev_name(busname, devname, devargs);
130         if (name == NULL)
131                 return -ENOMEM;
132
133         da = calloc(1, sizeof(*da));
134         if (da == NULL) {
135                 ret = -ENOMEM;
136                 goto err_name;
137         }
138
139         ret = rte_eal_devargs_parse(name, da);
140         if (ret)
141                 goto err_devarg;
142
143         ret = rte_eal_devargs_insert(da);
144         if (ret)
145                 goto err_devarg;
146
147         ret = bus->scan();
148         if (ret)
149                 goto err_devarg;
150
151         dev = bus->find_device(NULL, cmp_detached_dev_name, devname);
152         if (dev == NULL) {
153                 RTE_LOG(ERR, EAL, "Cannot find unplugged device (%s)\n",
154                         devname);
155                 ret = -ENODEV;
156                 goto err_devarg;
157         }
158
159         ret = bus->plug(dev);
160         if (ret) {
161                 RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n",
162                         dev->name);
163                 goto err_devarg;
164         }
165         free(name);
166         return 0;
167
168 err_devarg:
169         if (rte_eal_devargs_remove(busname, devname)) {
170                 free(da->args);
171                 free(da);
172         }
173 err_name:
174         free(name);
175         return ret;
176 }
177
178 int __rte_experimental
179 rte_eal_hotplug_remove(const char *busname, const char *devname)
180 {
181         struct rte_bus *bus;
182         struct rte_device *dev;
183         int ret;
184
185         bus = rte_bus_find_by_name(busname);
186         if (bus == NULL) {
187                 RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname);
188                 return -ENOENT;
189         }
190
191         if (bus->unplug == NULL) {
192                 RTE_LOG(ERR, EAL, "Function unplug not supported by bus (%s)\n",
193                         bus->name);
194                 return -ENOTSUP;
195         }
196
197         dev = bus->find_device(NULL, cmp_dev_name, devname);
198         if (dev == NULL) {
199                 RTE_LOG(ERR, EAL, "Cannot find plugged device (%s)\n", devname);
200                 return -EINVAL;
201         }
202
203         ret = bus->unplug(dev);
204         if (ret)
205                 RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
206                         dev->name);
207         rte_eal_devargs_remove(busname, devname);
208         return ret;
209 }