eal: fix positive error codes from probe/remove
[dpdk.git] / drivers / net / failsafe / failsafe_eal.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017 6WIND S.A.
3  * Copyright 2017 Mellanox Technologies, Ltd
4  */
5
6 #include <rte_string_fns.h>
7 #include <rte_malloc.h>
8
9 #include "failsafe_private.h"
10
11 static int
12 fs_ethdev_portid_get(const char *name, uint16_t *port_id)
13 {
14         uint16_t pid;
15         size_t len;
16
17         if (name == NULL) {
18                 DEBUG("Null pointer is specified\n");
19                 return -EINVAL;
20         }
21         len = strlen(name);
22         for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) {
23                 if (rte_eth_dev_is_valid_port(pid) &&
24                     !strncmp(name, rte_eth_devices[pid].device->name, len)) {
25                         *port_id = pid;
26                         return 0;
27                 }
28         }
29         return -ENODEV;
30 }
31
32 static int
33 fs_bus_init(struct rte_eth_dev *dev)
34 {
35         struct sub_device *sdev;
36         struct rte_devargs *da;
37         uint8_t i;
38         uint16_t pid;
39         int ret;
40
41         FOREACH_SUBDEV(sdev, i, dev) {
42                 if (sdev->state != DEV_PARSED)
43                         continue;
44                 da = &sdev->devargs;
45                 if (fs_ethdev_portid_get(da->name, &pid) != 0) {
46                         struct rte_eth_dev_owner pid_owner;
47
48                         ret = rte_eal_hotplug_add(da->bus->name,
49                                                   da->name,
50                                                   da->args);
51                         if (ret < 0) {
52                                 ERROR("sub_device %d probe failed %s%s%s", i,
53                                       rte_errno ? "(" : "",
54                                       rte_errno ? strerror(rte_errno) : "",
55                                       rte_errno ? ")" : "");
56                                 continue;
57                         }
58                         if (fs_ethdev_portid_get(da->name, &pid) != 0) {
59                                 ERROR("sub_device %d init went wrong", i);
60                                 return -ENODEV;
61                         }
62                         /*
63                          * The NEW callback tried to take ownership, check
64                          * whether it succeed or didn't.
65                          */
66                         rte_eth_dev_owner_get(pid, &pid_owner);
67                         if (pid_owner.id != PRIV(dev)->my_owner.id) {
68                                 INFO("sub_device %d owner(%s_%016"PRIX64") is not my,"
69                                      " owner(%s_%016"PRIX64"), will try again later",
70                                      i, pid_owner.name, pid_owner.id,
71                                      PRIV(dev)->my_owner.name,
72                                      PRIV(dev)->my_owner.id);
73                                 continue;
74                         }
75                 } else {
76                         /* The sub-device port was found. */
77                         char devstr[DEVARGS_MAXLEN] = "";
78                         struct rte_devargs *probed_da =
79                                         rte_eth_devices[pid].device->devargs;
80
81                         /* Take control of probed device. */
82                         free(da->args);
83                         memset(da, 0, sizeof(*da));
84                         if (probed_da != NULL)
85                                 snprintf(devstr, sizeof(devstr), "%s,%s",
86                                          probed_da->name, probed_da->args);
87                         else
88                                 strlcpy(devstr,
89                                         rte_eth_devices[pid].device->name,
90                                         sizeof(devstr));
91                         ret = rte_devargs_parse(da, devstr);
92                         if (ret) {
93                                 ERROR("Probed devargs parsing failed with code"
94                                       " %d", ret);
95                                 return ret;
96                         }
97                         INFO("Taking control of a probed sub device"
98                               " %d named %s", i, da->name);
99                         ret = rte_eth_dev_owner_set(pid, &PRIV(dev)->my_owner);
100                         if (ret < 0) {
101                                 INFO("sub_device %d owner set failed (%s), "
102                                      "will try again later", i, strerror(-ret));
103                                 continue;
104                         } else if (strncmp(rte_eth_devices[pid].device->name,
105                                    da->name, strlen(da->name)) != 0) {
106                                 /*
107                                  * The device probably was removed and its port
108                                  * id was reallocated before ownership set.
109                                  */
110                                 rte_eth_dev_owner_unset(pid,
111                                                         PRIV(dev)->my_owner.id);
112                                 INFO("sub_device %d was removed before taking"
113                                      " ownership, will try again later", i);
114                                 continue;
115                         }
116                 }
117                 sdev->sdev_port_id = pid;
118                 SUB_ID(sdev) = i;
119                 sdev->fs_port_id = dev->data->port_id;
120                 sdev->dev = ETH(sdev)->device;
121                 sdev->state = DEV_PROBED;
122         }
123         return 0;
124 }
125
126 int
127 failsafe_eal_init(struct rte_eth_dev *dev)
128 {
129         int ret;
130
131         ret = fs_bus_init(dev);
132         if (ret)
133                 return ret;
134         if (PRIV(dev)->state < DEV_PROBED)
135                 PRIV(dev)->state = DEV_PROBED;
136         fs_switch_dev(dev, NULL);
137         return 0;
138 }
139
140 static int
141 fs_bus_uninit(struct rte_eth_dev *dev)
142 {
143         struct sub_device *sdev = NULL;
144         uint8_t i;
145         int sdev_ret;
146         int ret = 0;
147
148         FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
149                 sdev_ret = rte_dev_remove(sdev->dev);
150                 if (sdev_ret < 0) {
151                         ERROR("Failed to remove requested device %s (err: %d)",
152                               sdev->dev->name, sdev_ret);
153                         continue;
154                 }
155                 sdev->state = DEV_PROBED - 1;
156         }
157         return ret;
158 }
159
160 int
161 failsafe_eal_uninit(struct rte_eth_dev *dev)
162 {
163         int ret;
164
165         ret = fs_bus_uninit(dev);
166         PRIV(dev)->state = DEV_PROBED - 1;
167         return ret;
168 }