xref: /dpdk/drivers/net/failsafe/failsafe_eal.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
1009c327cSOlivier Matz /* SPDX-License-Identifier: BSD-3-Clause
2a46f8d58SGaetan Rivet  * Copyright 2017 6WIND S.A.
35feecc57SShahaf Shuler  * Copyright 2017 Mellanox Technologies, Ltd
4a46f8d58SGaetan Rivet  */
5a46f8d58SGaetan Rivet 
6a04322f6SDavid Marchand #include <bus_driver.h>
76723c0fcSBruce Richardson #include <rte_string_fns.h>
8a46f8d58SGaetan Rivet #include <rte_malloc.h>
9a46f8d58SGaetan Rivet 
10a46f8d58SGaetan Rivet #include "failsafe_private.h"
11a46f8d58SGaetan Rivet 
12a46f8d58SGaetan Rivet static int
1353a2d53fSMatan Azrad fs_ethdev_portid_get(const char *name, uint16_t *port_id)
1453a2d53fSMatan Azrad {
1553a2d53fSMatan Azrad 	uint16_t pid;
1653a2d53fSMatan Azrad 	size_t len;
1753a2d53fSMatan Azrad 
1853a2d53fSMatan Azrad 	if (name == NULL) {
19*f665790aSDavid Marchand 		DEBUG("Null pointer is specified");
2053a2d53fSMatan Azrad 		return -EINVAL;
2153a2d53fSMatan Azrad 	}
2253a2d53fSMatan Azrad 	len = strlen(name);
237fda13d3SMatan Azrad 	for (pid = 0; pid < RTE_MAX_ETHPORTS; pid++) {
247fda13d3SMatan Azrad 		if (rte_eth_dev_is_valid_port(pid) &&
257fda13d3SMatan Azrad 		    !strncmp(name, rte_eth_devices[pid].device->name, len)) {
2653a2d53fSMatan Azrad 			*port_id = pid;
2753a2d53fSMatan Azrad 			return 0;
2853a2d53fSMatan Azrad 		}
2953a2d53fSMatan Azrad 	}
3053a2d53fSMatan Azrad 	return -ENODEV;
3153a2d53fSMatan Azrad }
3253a2d53fSMatan Azrad 
3353a2d53fSMatan Azrad static int
34a46f8d58SGaetan Rivet fs_bus_init(struct rte_eth_dev *dev)
35a46f8d58SGaetan Rivet {
36a46f8d58SGaetan Rivet 	struct sub_device *sdev;
37a46f8d58SGaetan Rivet 	struct rte_devargs *da;
38a46f8d58SGaetan Rivet 	uint8_t i;
3953a2d53fSMatan Azrad 	uint16_t pid;
40a46f8d58SGaetan Rivet 	int ret;
41a46f8d58SGaetan Rivet 
42a46f8d58SGaetan Rivet 	FOREACH_SUBDEV(sdev, i, dev) {
43a46f8d58SGaetan Rivet 		if (sdev->state != DEV_PARSED)
44a46f8d58SGaetan Rivet 			continue;
45a46f8d58SGaetan Rivet 		da = &sdev->devargs;
4653a2d53fSMatan Azrad 		if (fs_ethdev_portid_get(da->name, &pid) != 0) {
477fda13d3SMatan Azrad 			struct rte_eth_dev_owner pid_owner;
487fda13d3SMatan Azrad 
49a46f8d58SGaetan Rivet 			ret = rte_eal_hotplug_add(da->bus->name,
50a46f8d58SGaetan Rivet 						  da->name,
51a46f8d58SGaetan Rivet 						  da->args);
5275b66decSIlya Maximets 			if (ret < 0) {
53a46f8d58SGaetan Rivet 				ERROR("sub_device %d probe failed %s%s%s", i,
54a46f8d58SGaetan Rivet 				      rte_errno ? "(" : "",
55a46f8d58SGaetan Rivet 				      rte_errno ? strerror(rte_errno) : "",
56a46f8d58SGaetan Rivet 				      rte_errno ? ")" : "");
57a46f8d58SGaetan Rivet 				continue;
58a46f8d58SGaetan Rivet 			}
5953a2d53fSMatan Azrad 			if (fs_ethdev_portid_get(da->name, &pid) != 0) {
60a46f8d58SGaetan Rivet 				ERROR("sub_device %d init went wrong", i);
61a46f8d58SGaetan Rivet 				return -ENODEV;
62a46f8d58SGaetan Rivet 			}
637fda13d3SMatan Azrad 			/*
647fda13d3SMatan Azrad 			 * The NEW callback tried to take ownership, check
657fda13d3SMatan Azrad 			 * whether it succeed or didn't.
667fda13d3SMatan Azrad 			 */
677fda13d3SMatan Azrad 			rte_eth_dev_owner_get(pid, &pid_owner);
687fda13d3SMatan Azrad 			if (pid_owner.id != PRIV(dev)->my_owner.id) {
697fda13d3SMatan Azrad 				INFO("sub_device %d owner(%s_%016"PRIX64") is not my,"
707fda13d3SMatan Azrad 				     " owner(%s_%016"PRIX64"), will try again later",
717fda13d3SMatan Azrad 				     i, pid_owner.name, pid_owner.id,
727fda13d3SMatan Azrad 				     PRIV(dev)->my_owner.name,
737fda13d3SMatan Azrad 				     PRIV(dev)->my_owner.id);
747fda13d3SMatan Azrad 				continue;
757fda13d3SMatan Azrad 			}
7653a2d53fSMatan Azrad 		} else {
777fda13d3SMatan Azrad 			/* The sub-device port was found. */
7853a2d53fSMatan Azrad 			char devstr[DEVARGS_MAXLEN] = "";
7953a2d53fSMatan Azrad 			struct rte_devargs *probed_da =
8053a2d53fSMatan Azrad 					rte_eth_devices[pid].device->devargs;
8153a2d53fSMatan Azrad 
827fda13d3SMatan Azrad 			/* Take control of probed device. */
8364051bb1SXueming Li 			rte_devargs_reset(da);
8453a2d53fSMatan Azrad 			memset(da, 0, sizeof(*da));
8553a2d53fSMatan Azrad 			if (probed_da != NULL)
8653a2d53fSMatan Azrad 				snprintf(devstr, sizeof(devstr), "%s,%s",
8753a2d53fSMatan Azrad 					 probed_da->name, probed_da->args);
8853a2d53fSMatan Azrad 			else
896723c0fcSBruce Richardson 				strlcpy(devstr,
906723c0fcSBruce Richardson 					rte_eth_devices[pid].device->name,
916723c0fcSBruce Richardson 					sizeof(devstr));
92a23bc2c4SGaetan Rivet 			ret = rte_devargs_parse(da, devstr);
9353a2d53fSMatan Azrad 			if (ret) {
9453a2d53fSMatan Azrad 				ERROR("Probed devargs parsing failed with code"
9553a2d53fSMatan Azrad 				      " %d", ret);
9653a2d53fSMatan Azrad 				return ret;
9753a2d53fSMatan Azrad 			}
9853a2d53fSMatan Azrad 			INFO("Taking control of a probed sub device"
9953a2d53fSMatan Azrad 			      " %d named %s", i, da->name);
100dcd0c9c3SMatan Azrad 			ret = rte_eth_dev_owner_set(pid, &PRIV(dev)->my_owner);
1019df324adSGaetan Rivet 			if (ret < 0) {
102dcd0c9c3SMatan Azrad 				INFO("sub_device %d owner set failed (%s), "
1039df324adSGaetan Rivet 				     "will try again later", i, strerror(-ret));
104dcd0c9c3SMatan Azrad 				continue;
1057fda13d3SMatan Azrad 			} else if (strncmp(rte_eth_devices[pid].device->name,
1067fda13d3SMatan Azrad 				   da->name, strlen(da->name)) != 0) {
107dcd0c9c3SMatan Azrad 				/*
1087fda13d3SMatan Azrad 				 * The device probably was removed and its port
1097fda13d3SMatan Azrad 				 * id was reallocated before ownership set.
110dcd0c9c3SMatan Azrad 				 */
1117fda13d3SMatan Azrad 				rte_eth_dev_owner_unset(pid,
1127fda13d3SMatan Azrad 							PRIV(dev)->my_owner.id);
1137fda13d3SMatan Azrad 				INFO("sub_device %d was removed before taking"
114dcd0c9c3SMatan Azrad 				     " ownership, will try again later", i);
115dcd0c9c3SMatan Azrad 				continue;
116dcd0c9c3SMatan Azrad 			}
1177fda13d3SMatan Azrad 		}
1182f4b9983SRaslan Darawsheh 		sdev->sdev_port_id = pid;
119b737a1eeSGaetan Rivet 		SUB_ID(sdev) = i;
120fa7bb47aSRaslan Darawsheh 		sdev->fs_port_id = dev->data->port_id;
121a46f8d58SGaetan Rivet 		sdev->dev = ETH(sdev)->device;
122a46f8d58SGaetan Rivet 		sdev->state = DEV_PROBED;
123a46f8d58SGaetan Rivet 	}
124a46f8d58SGaetan Rivet 	return 0;
125a46f8d58SGaetan Rivet }
126a46f8d58SGaetan Rivet 
127a46f8d58SGaetan Rivet int
128a46f8d58SGaetan Rivet failsafe_eal_init(struct rte_eth_dev *dev)
129a46f8d58SGaetan Rivet {
130a46f8d58SGaetan Rivet 	int ret;
131a46f8d58SGaetan Rivet 
132a46f8d58SGaetan Rivet 	ret = fs_bus_init(dev);
133a46f8d58SGaetan Rivet 	if (ret)
134a46f8d58SGaetan Rivet 		return ret;
135ebea83f8SGaetan Rivet 	if (PRIV(dev)->state < DEV_PROBED)
136ebea83f8SGaetan Rivet 		PRIV(dev)->state = DEV_PROBED;
137598fb8aeSGaetan Rivet 	fs_switch_dev(dev, NULL);
138a46f8d58SGaetan Rivet 	return 0;
139a46f8d58SGaetan Rivet }
140a46f8d58SGaetan Rivet 
141a46f8d58SGaetan Rivet static int
142a46f8d58SGaetan Rivet fs_bus_uninit(struct rte_eth_dev *dev)
143a46f8d58SGaetan Rivet {
144a46f8d58SGaetan Rivet 	struct sub_device *sdev = NULL;
145a46f8d58SGaetan Rivet 	uint8_t i;
1466969a22bSRaslan Darawsheh 	int sdev_ret;
1476969a22bSRaslan Darawsheh 	int ret = 0;
148a46f8d58SGaetan Rivet 
149a46f8d58SGaetan Rivet 	FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_PROBED) {
150911462ebSThomas Monjalon 		sdev_ret = rte_dev_remove(sdev->dev);
15175b66decSIlya Maximets 		if (sdev_ret < 0) {
1526969a22bSRaslan Darawsheh 			ERROR("Failed to remove requested device %s (err: %d)",
1536969a22bSRaslan Darawsheh 			      sdev->dev->name, sdev_ret);
154a46f8d58SGaetan Rivet 			continue;
155a46f8d58SGaetan Rivet 		}
156a46f8d58SGaetan Rivet 		sdev->state = DEV_PROBED - 1;
157a46f8d58SGaetan Rivet 	}
1586969a22bSRaslan Darawsheh 	return ret;
159a46f8d58SGaetan Rivet }
160a46f8d58SGaetan Rivet 
161a46f8d58SGaetan Rivet int
162a46f8d58SGaetan Rivet failsafe_eal_uninit(struct rte_eth_dev *dev)
163a46f8d58SGaetan Rivet {
164a46f8d58SGaetan Rivet 	int ret;
165a46f8d58SGaetan Rivet 
166a46f8d58SGaetan Rivet 	ret = fs_bus_uninit(dev);
167ebea83f8SGaetan Rivet 	PRIV(dev)->state = DEV_PROBED - 1;
1686969a22bSRaslan Darawsheh 	return ret;
169a46f8d58SGaetan Rivet }
170