xref: /dpdk/drivers/net/failsafe/failsafe_eal.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
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 }
169