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