xref: /dpdk/drivers/net/failsafe/failsafe_eal.c (revision 2d0c29a37a9c080c1cccb1ad7941aba2ccf5437e)
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 		sdev->sdev_port_id = pid;
116 		SUB_ID(sdev) = i;
117 		sdev->fs_port_id = dev->data->port_id;
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 }
167