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