net/failsafe: use SPDX tags in 6WIND copyrighted files
[dpdk.git] / drivers / net / failsafe / failsafe.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017 6WIND S.A.
3  * Copyright 2017 Mellanox.
4  */
5
6 #include <rte_alarm.h>
7 #include <rte_malloc.h>
8 #include <rte_ethdev_driver.h>
9 #include <rte_ethdev_vdev.h>
10 #include <rte_devargs.h>
11 #include <rte_kvargs.h>
12 #include <rte_bus_vdev.h>
13
14 #include "failsafe_private.h"
15
16 const char pmd_failsafe_driver_name[] = FAILSAFE_DRIVER_NAME;
17 static const struct rte_eth_link eth_link = {
18         .link_speed = ETH_SPEED_NUM_10G,
19         .link_duplex = ETH_LINK_FULL_DUPLEX,
20         .link_status = ETH_LINK_UP,
21         .link_autoneg = ETH_LINK_AUTONEG,
22 };
23
24 static int
25 fs_sub_device_alloc(struct rte_eth_dev *dev,
26                 const char *params)
27 {
28         uint8_t nb_subs;
29         int ret;
30         int i;
31
32         ret = failsafe_args_count_subdevice(dev, params);
33         if (ret)
34                 return ret;
35         if (PRIV(dev)->subs_tail > FAILSAFE_MAX_ETHPORTS) {
36                 ERROR("Cannot allocate more than %d ports",
37                         FAILSAFE_MAX_ETHPORTS);
38                 return -ENOSPC;
39         }
40         nb_subs = PRIV(dev)->subs_tail;
41         PRIV(dev)->subs = rte_zmalloc(NULL,
42                         sizeof(struct sub_device) * nb_subs,
43                         RTE_CACHE_LINE_SIZE);
44         if (PRIV(dev)->subs == NULL) {
45                 ERROR("Could not allocate sub_devices");
46                 return -ENOMEM;
47         }
48         /* Initiate static sub devices linked list. */
49         for (i = 1; i < nb_subs; i++)
50                 PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs + i;
51         PRIV(dev)->subs[i - 1].next = PRIV(dev)->subs;
52         return 0;
53 }
54
55 static void
56 fs_sub_device_free(struct rte_eth_dev *dev)
57 {
58         rte_free(PRIV(dev)->subs);
59 }
60
61 static void fs_hotplug_alarm(void *arg);
62
63 int
64 failsafe_hotplug_alarm_install(struct rte_eth_dev *dev)
65 {
66         int ret;
67
68         if (dev == NULL)
69                 return -EINVAL;
70         if (PRIV(dev)->pending_alarm)
71                 return 0;
72         ret = rte_eal_alarm_set(hotplug_poll * 1000,
73                                 fs_hotplug_alarm,
74                                 dev);
75         if (ret) {
76                 ERROR("Could not set up plug-in event detection");
77                 return ret;
78         }
79         PRIV(dev)->pending_alarm = 1;
80         return 0;
81 }
82
83 int
84 failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev)
85 {
86         int ret = 0;
87
88         if (PRIV(dev)->pending_alarm) {
89                 rte_errno = 0;
90                 rte_eal_alarm_cancel(fs_hotplug_alarm, dev);
91                 if (rte_errno) {
92                         ERROR("rte_eal_alarm_cancel failed (errno: %s)",
93                               strerror(rte_errno));
94                         ret = -rte_errno;
95                 } else {
96                         PRIV(dev)->pending_alarm = 0;
97                 }
98         }
99         return ret;
100 }
101
102 static void
103 fs_hotplug_alarm(void *arg)
104 {
105         struct rte_eth_dev *dev = arg;
106         struct sub_device *sdev;
107         int ret;
108         uint8_t i;
109
110         if (!PRIV(dev)->pending_alarm)
111                 return;
112         PRIV(dev)->pending_alarm = 0;
113         FOREACH_SUBDEV(sdev, i, dev)
114                 if (sdev->state != PRIV(dev)->state)
115                         break;
116         /* if we have non-probed device */
117         if (i != PRIV(dev)->subs_tail) {
118                 ret = failsafe_eth_dev_state_sync(dev);
119                 if (ret)
120                         ERROR("Unable to synchronize sub_device state");
121         }
122         failsafe_dev_remove(dev);
123         ret = failsafe_hotplug_alarm_install(dev);
124         if (ret)
125                 ERROR("Unable to set up next alarm");
126 }
127
128 static int
129 fs_eth_dev_create(struct rte_vdev_device *vdev)
130 {
131         struct rte_eth_dev *dev;
132         struct ether_addr *mac;
133         struct fs_priv *priv;
134         struct sub_device *sdev;
135         const char *params;
136         unsigned int socket_id;
137         uint8_t i;
138         int ret;
139
140         dev = NULL;
141         priv = NULL;
142         socket_id = rte_socket_id();
143         INFO("Creating fail-safe device on NUMA socket %u", socket_id);
144         params = rte_vdev_device_args(vdev);
145         if (params == NULL) {
146                 ERROR("This PMD requires sub-devices, none provided");
147                 return -1;
148         }
149         dev = rte_eth_vdev_allocate(vdev, sizeof(*priv));
150         if (dev == NULL) {
151                 ERROR("Unable to allocate rte_eth_dev");
152                 return -1;
153         }
154         priv = PRIV(dev);
155         priv->dev = dev;
156         dev->dev_ops = &failsafe_ops;
157         dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0];
158         dev->data->dev_link = eth_link;
159         PRIV(dev)->nb_mac_addr = 1;
160         TAILQ_INIT(&PRIV(dev)->flow_list);
161         dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst;
162         dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst;
163         ret = fs_sub_device_alloc(dev, params);
164         if (ret) {
165                 ERROR("Could not allocate sub_devices");
166                 goto free_dev;
167         }
168         ret = failsafe_args_parse(dev, params);
169         if (ret)
170                 goto free_subs;
171         ret = rte_eth_dev_owner_new(&priv->my_owner.id);
172         if (ret) {
173                 ERROR("Failed to get unique owner identifier");
174                 goto free_args;
175         }
176         snprintf(priv->my_owner.name, sizeof(priv->my_owner.name),
177                  FAILSAFE_OWNER_NAME);
178         ret = failsafe_eal_init(dev);
179         if (ret)
180                 goto free_args;
181         ret = failsafe_hotplug_alarm_install(dev);
182         if (ret) {
183                 ERROR("Could not set up plug-in event detection");
184                 goto free_args;
185         }
186         mac = &dev->data->mac_addrs[0];
187         if (mac_from_arg) {
188                 /*
189                  * If MAC address was provided as a parameter,
190                  * apply to all probed slaves.
191                  */
192                 FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
193                         ret = rte_eth_dev_default_mac_addr_set(PORT_ID(sdev),
194                                                                mac);
195                         if (ret) {
196                                 ERROR("Failed to set default MAC address");
197                                 goto free_args;
198                         }
199                 }
200         } else {
201                 /*
202                  * Use the ether_addr from first probed
203                  * device, either preferred or fallback.
204                  */
205                 FOREACH_SUBDEV(sdev, i, dev)
206                         if (sdev->state >= DEV_PROBED) {
207                                 ether_addr_copy(&ETH(sdev)->data->mac_addrs[0],
208                                                 mac);
209                                 break;
210                         }
211                 /*
212                  * If no device has been probed and no ether_addr
213                  * has been provided on the command line, use a random
214                  * valid one.
215                  * It will be applied during future slave state syncs to
216                  * probed slaves.
217                  */
218                 if (i == priv->subs_tail)
219                         eth_random_addr(&mac->addr_bytes[0]);
220         }
221         INFO("MAC address is %02x:%02x:%02x:%02x:%02x:%02x",
222                 mac->addr_bytes[0], mac->addr_bytes[1],
223                 mac->addr_bytes[2], mac->addr_bytes[3],
224                 mac->addr_bytes[4], mac->addr_bytes[5]);
225         dev->data->dev_flags |= RTE_ETH_DEV_INTR_LSC;
226         PRIV(dev)->intr_handle = (struct rte_intr_handle){
227                 .fd = -1,
228                 .type = RTE_INTR_HANDLE_EXT,
229         };
230         return 0;
231 free_args:
232         failsafe_args_free(dev);
233 free_subs:
234         fs_sub_device_free(dev);
235 free_dev:
236         rte_free(PRIV(dev));
237         rte_eth_dev_release_port(dev);
238         return -1;
239 }
240
241 static int
242 fs_rte_eth_free(const char *name)
243 {
244         struct rte_eth_dev *dev;
245         int ret;
246
247         dev = rte_eth_dev_allocated(name);
248         if (dev == NULL)
249                 return -ENODEV;
250         ret = failsafe_eal_uninit(dev);
251         if (ret)
252                 ERROR("Error while uninitializing sub-EAL");
253         failsafe_args_free(dev);
254         fs_sub_device_free(dev);
255         rte_free(PRIV(dev));
256         rte_eth_dev_release_port(dev);
257         return ret;
258 }
259
260 static int
261 rte_pmd_failsafe_probe(struct rte_vdev_device *vdev)
262 {
263         const char *name;
264
265         name = rte_vdev_device_name(vdev);
266         INFO("Initializing " FAILSAFE_DRIVER_NAME " for %s",
267                         name);
268         return fs_eth_dev_create(vdev);
269 }
270
271 static int
272 rte_pmd_failsafe_remove(struct rte_vdev_device *vdev)
273 {
274         const char *name;
275
276         name = rte_vdev_device_name(vdev);
277         INFO("Uninitializing " FAILSAFE_DRIVER_NAME " for %s", name);
278         return fs_rte_eth_free(name);
279 }
280
281 static struct rte_vdev_driver failsafe_drv = {
282         .probe = rte_pmd_failsafe_probe,
283         .remove = rte_pmd_failsafe_remove,
284 };
285
286 RTE_PMD_REGISTER_VDEV(net_failsafe, failsafe_drv);
287 RTE_PMD_REGISTER_PARAM_STRING(net_failsafe, PMD_FAILSAFE_PARAM_STRING);