xref: /dpdk/drivers/net/failsafe/failsafe_private.h (revision 2b843cac232eb3f2fa79e4254e21766817e2019f)
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 
6b28f28aeSDharmik Thakkar #ifndef _ETH_FAILSAFE_PRIVATE_H_
7b28f28aeSDharmik Thakkar #define _ETH_FAILSAFE_PRIVATE_H_
8a46f8d58SGaetan Rivet 
933fcf207SAdrien Mazarguil #include <stdint.h>
10b737a1eeSGaetan Rivet #include <sys/queue.h>
11655fcd68SMatan Azrad #include <pthread.h>
12b737a1eeSGaetan Rivet 
13598fb8aeSGaetan Rivet #include <rte_atomic.h>
141acb7f54SDavid Marchand #include <dev_driver.h>
15df96fd0dSBruce Richardson #include <ethdev_driver.h>
16a46f8d58SGaetan Rivet #include <rte_devargs.h>
1733fcf207SAdrien Mazarguil #include <rte_flow.h>
189e0360aeSMoti Haimovsky #include <rte_interrupts.h>
19a46f8d58SGaetan Rivet 
20a46f8d58SGaetan Rivet #define FAILSAFE_DRIVER_NAME "Fail-safe PMD"
21dcd0c9c3SMatan Azrad #define FAILSAFE_OWNER_NAME "Fail-safe"
22a46f8d58SGaetan Rivet 
23a46f8d58SGaetan Rivet #define PMD_FAILSAFE_MAC_KVARG "mac"
24ebea83f8SGaetan Rivet #define PMD_FAILSAFE_HOTPLUG_POLL_KVARG "hotplug_poll"
25a46f8d58SGaetan Rivet #define PMD_FAILSAFE_PARAM_STRING	\
26a46f8d58SGaetan Rivet 	"dev(<ifc>),"			\
27a0194d82SGaetan Rivet 	"exec(<shell command>),"	\
28d1b961dbSMatan Azrad 	"fd(<fd number>),"		\
29ebea83f8SGaetan Rivet 	"mac=mac_addr,"			\
30ebea83f8SGaetan Rivet 	"hotplug_poll=u64"		\
31a46f8d58SGaetan Rivet 	""
32a46f8d58SGaetan Rivet 
33ebea83f8SGaetan Rivet #define FAILSAFE_HOTPLUG_DEFAULT_TIMEOUT_MS 2000
34ebea83f8SGaetan Rivet 
35a46f8d58SGaetan Rivet #define FAILSAFE_MAX_ETHPORTS 2
36a46f8d58SGaetan Rivet #define FAILSAFE_MAX_ETHADDR 128
37a46f8d58SGaetan Rivet 
3853a2d53fSMatan Azrad #define DEVARGS_MAXLEN 4096
3953a2d53fSMatan Azrad 
40709676bcSMoti Haimovsky enum rxp_service_state {
41709676bcSMoti Haimovsky 	SS_NO_SERVICE = 0,
42709676bcSMoti Haimovsky 	SS_REGISTERED,
43709676bcSMoti Haimovsky 	SS_READY,
44709676bcSMoti Haimovsky 	SS_RUNNING,
45709676bcSMoti Haimovsky };
46709676bcSMoti Haimovsky 
47a46f8d58SGaetan Rivet /* TYPES */
48a46f8d58SGaetan Rivet 
49f234e5bdSMoti Haimovsky struct rx_proxy {
50f234e5bdSMoti Haimovsky 	/* epoll file descriptor */
51f234e5bdSMoti Haimovsky 	int efd;
52f234e5bdSMoti Haimovsky 	/* event vector to be used by epoll */
53f234e5bdSMoti Haimovsky 	struct rte_epoll_event *evec;
54709676bcSMoti Haimovsky 	/* rte service id */
55709676bcSMoti Haimovsky 	uint32_t sid;
56709676bcSMoti Haimovsky 	/* service core id */
57709676bcSMoti Haimovsky 	uint32_t scid;
58709676bcSMoti Haimovsky 	enum rxp_service_state sstate;
59f234e5bdSMoti Haimovsky };
60f234e5bdSMoti Haimovsky 
61b9663f60SYunjian Wang #define FS_RX_PROXY_INIT (struct rx_proxy){ \
62b9663f60SYunjian Wang 	.efd = -1, \
63b9663f60SYunjian Wang 	.evec = NULL, \
64b9663f60SYunjian Wang 	.sid = 0, \
65b9663f60SYunjian Wang 	.scid = 0, \
66b9663f60SYunjian Wang 	.sstate = SS_NO_SERVICE, \
67b9663f60SYunjian Wang }
68b9663f60SYunjian Wang 
69a46f8d58SGaetan Rivet struct rxq {
70a46f8d58SGaetan Rivet 	struct fs_priv *priv;
71a46f8d58SGaetan Rivet 	uint16_t qid;
728052bbd9SMatan Azrad 	/* next sub_device to poll */
738052bbd9SMatan Azrad 	struct sub_device *sdev;
74a46f8d58SGaetan Rivet 	unsigned int socket_id;
759e0360aeSMoti Haimovsky 	int event_fd;
769e0360aeSMoti Haimovsky 	unsigned int enable_events:1;
77a46f8d58SGaetan Rivet 	struct rte_eth_rxq_info info;
78598fb8aeSGaetan Rivet 	rte_atomic64_t refcnt[];
79a46f8d58SGaetan Rivet };
80a46f8d58SGaetan Rivet 
81a46f8d58SGaetan Rivet struct txq {
82a46f8d58SGaetan Rivet 	struct fs_priv *priv;
83a46f8d58SGaetan Rivet 	uint16_t qid;
84a46f8d58SGaetan Rivet 	unsigned int socket_id;
85a46f8d58SGaetan Rivet 	struct rte_eth_txq_info info;
86598fb8aeSGaetan Rivet 	rte_atomic64_t refcnt[];
87a46f8d58SGaetan Rivet };
88a46f8d58SGaetan Rivet 
89b737a1eeSGaetan Rivet struct rte_flow {
90b737a1eeSGaetan Rivet 	TAILQ_ENTRY(rte_flow) next;
91b737a1eeSGaetan Rivet 	/* sub_flows */
92b737a1eeSGaetan Rivet 	struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS];
93b737a1eeSGaetan Rivet 	/* flow description for synchronization */
9433fcf207SAdrien Mazarguil 	struct rte_flow_conv_rule rule;
9533fcf207SAdrien Mazarguil 	uint8_t rule_data[];
96b737a1eeSGaetan Rivet };
97b737a1eeSGaetan Rivet 
98a46f8d58SGaetan Rivet enum dev_state {
99a46f8d58SGaetan Rivet 	DEV_UNDEFINED,
100a46f8d58SGaetan Rivet 	DEV_PARSED,
101a46f8d58SGaetan Rivet 	DEV_PROBED,
102a46f8d58SGaetan Rivet 	DEV_ACTIVE,
103a46f8d58SGaetan Rivet 	DEV_STARTED,
104a46f8d58SGaetan Rivet };
105a46f8d58SGaetan Rivet 
1069dda3e33SMatan Azrad struct fs_stats {
1079dda3e33SMatan Azrad 	struct rte_eth_stats stats;
1089dda3e33SMatan Azrad 	uint64_t timestamp;
1099dda3e33SMatan Azrad };
1109dda3e33SMatan Azrad 
1112f4b9983SRaslan Darawsheh /*
1122f4b9983SRaslan Darawsheh  * Allocated in shared memory.
1132f4b9983SRaslan Darawsheh  */
114a46f8d58SGaetan Rivet struct sub_device {
115a46f8d58SGaetan Rivet 	/* Exhaustive DPDK device description */
1168052bbd9SMatan Azrad 	struct sub_device *next;
117a46f8d58SGaetan Rivet 	struct rte_devargs devargs;
1182f4b9983SRaslan Darawsheh 	struct rte_bus *bus; /* for primary process only. */
1192f4b9983SRaslan Darawsheh 	struct rte_device *dev; /* for primary process only. */
120b737a1eeSGaetan Rivet 	uint8_t sid;
121a46f8d58SGaetan Rivet 	/* Device state machine */
122a46f8d58SGaetan Rivet 	enum dev_state state;
1236265ab51SMatan Azrad 	/* Last stats snapshot passed to user */
1249dda3e33SMatan Azrad 	struct fs_stats stats_snapshot;
125a0194d82SGaetan Rivet 	/* Some device are defined as a command line */
126a0194d82SGaetan Rivet 	char *cmdline;
127d1b961dbSMatan Azrad 	/* Others are retrieved through a file descriptor */
128d1b961dbSMatan Azrad 	char *fd_str;
129598fb8aeSGaetan Rivet 	/* fail-safe device backreference */
130fa7bb47aSRaslan Darawsheh 	uint16_t fs_port_id; /* shared between processes */
1312f4b9983SRaslan Darawsheh 	/* sub device port id*/
1322f4b9983SRaslan Darawsheh 	uint16_t sdev_port_id; /* shared between processes */
133598fb8aeSGaetan Rivet 	/* flag calling for recollection */
134598fb8aeSGaetan Rivet 	volatile unsigned int remove:1;
1352cc52cd7SGaetan Rivet 	/* flow isolation state */
1362cc52cd7SGaetan Rivet 	int flow_isolated:1;
1370545c580SMatan Azrad 	/* RMV callback registration state */
1380545c580SMatan Azrad 	unsigned int rmv_callback:1;
1390545c580SMatan Azrad 	/* LSC callback registration state */
1400545c580SMatan Azrad 	unsigned int lsc_callback:1;
141a46f8d58SGaetan Rivet };
142a46f8d58SGaetan Rivet 
14308647012SRaslan Darawsheh /*
14408647012SRaslan Darawsheh  * This is referenced by eth_dev->data->dev_private
14508647012SRaslan Darawsheh  * This is shared between processes.
14608647012SRaslan Darawsheh  */
147a46f8d58SGaetan Rivet struct fs_priv {
14808647012SRaslan Darawsheh 	struct rte_eth_dev_data *data; /* backreference to shared data. */
149a46f8d58SGaetan Rivet 	/*
150a46f8d58SGaetan Rivet 	 * Set of sub_devices.
151a46f8d58SGaetan Rivet 	 * subs[0] is the preferred device
15239fab5a0SStephen Hemminger 	 * any other is just another sub device
153a46f8d58SGaetan Rivet 	 */
1542f4b9983SRaslan Darawsheh 	struct sub_device *subs;  /* shared between processes */
155a46f8d58SGaetan Rivet 	uint8_t subs_head; /* if head == tail, no subs */
156a46f8d58SGaetan Rivet 	uint8_t subs_tail; /* first invalid */
157a46f8d58SGaetan Rivet 	uint8_t subs_tx; /* current emitting device */
158a46f8d58SGaetan Rivet 	uint8_t current_probed;
159b737a1eeSGaetan Rivet 	/* flow mapping */
160b737a1eeSGaetan Rivet 	TAILQ_HEAD(sub_flows, rte_flow) flow_list;
161a46f8d58SGaetan Rivet 	/* current number of mac_addr slots allocated. */
162a46f8d58SGaetan Rivet 	uint32_t nb_mac_addr;
1636d13ea8eSOlivier Matz 	struct rte_ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR];
164a46f8d58SGaetan Rivet 	uint32_t mac_addr_pool[FAILSAFE_MAX_ETHADDR];
165901efc0dSEvgeny Im 	uint32_t nb_mcast_addr;
1666d13ea8eSOlivier Matz 	struct rte_ether_addr *mcast_addrs;
167a46f8d58SGaetan Rivet 	/* current capabilities */
168dcd0c9c3SMatan Azrad 	struct rte_eth_dev_owner my_owner; /* Unique owner. */
169d61138d4SHarman Kalra 	struct rte_intr_handle *intr_handle; /* Port interrupt handle. */
170ebea83f8SGaetan Rivet 	/*
171ebea83f8SGaetan Rivet 	 * Fail-safe state machine.
172ebea83f8SGaetan Rivet 	 * This level will be tracking state of the EAL and eth
173ebea83f8SGaetan Rivet 	 * layer at large as defined by the user application.
174ebea83f8SGaetan Rivet 	 * It will then steer the sub_devices toward the same
175ebea83f8SGaetan Rivet 	 * synchronized state.
176ebea83f8SGaetan Rivet 	 */
177ebea83f8SGaetan Rivet 	enum dev_state state;
1786265ab51SMatan Azrad 	struct rte_eth_stats stats_accumulator;
179f234e5bdSMoti Haimovsky 	/*
180f234e5bdSMoti Haimovsky 	 * Rx interrupts/events proxy.
181f234e5bdSMoti Haimovsky 	 * The PMD issues Rx events to the EAL on behalf of its subdevices,
182f234e5bdSMoti Haimovsky 	 * it does that by registering an event-fd for each of its queues with
183709676bcSMoti Haimovsky 	 * the EAL. A PMD service thread listens to all the Rx events from the
184709676bcSMoti Haimovsky 	 * subdevices, when an Rx event is issued by a subdevice it will be
185709676bcSMoti Haimovsky 	 * caught by this service with will trigger an Rx event in the
186709676bcSMoti Haimovsky 	 * appropriate failsafe Rx queue.
187f234e5bdSMoti Haimovsky 	 */
188f234e5bdSMoti Haimovsky 	struct rx_proxy rxp;
189655fcd68SMatan Azrad 	pthread_mutex_t hotplug_mutex;
190655fcd68SMatan Azrad 	/* Hot-plug mutex is locked by the alarm mechanism. */
191655fcd68SMatan Azrad 	volatile unsigned int alarm_lock:1;
192ebea83f8SGaetan Rivet 	unsigned int pending_alarm:1; /* An alarm is pending */
1932cc52cd7SGaetan Rivet 	/* flow isolation state */
1942cc52cd7SGaetan Rivet 	int flow_isolated:1;
195a46f8d58SGaetan Rivet };
196a46f8d58SGaetan Rivet 
1979e0360aeSMoti Haimovsky /* FAILSAFE_INTR */
1989e0360aeSMoti Haimovsky 
1999e0360aeSMoti Haimovsky int failsafe_rx_intr_install(struct rte_eth_dev *dev);
2009e0360aeSMoti Haimovsky void failsafe_rx_intr_uninstall(struct rte_eth_dev *dev);
201f234e5bdSMoti Haimovsky int failsafe_rx_intr_install_subdevice(struct sub_device *sdev);
202f234e5bdSMoti Haimovsky void failsafe_rx_intr_uninstall_subdevice(struct sub_device *sdev);
2039e0360aeSMoti Haimovsky 
204ebea83f8SGaetan Rivet /* MISC */
205ebea83f8SGaetan Rivet 
206ebea83f8SGaetan Rivet int failsafe_hotplug_alarm_install(struct rte_eth_dev *dev);
207ebea83f8SGaetan Rivet int failsafe_hotplug_alarm_cancel(struct rte_eth_dev *dev);
208ebea83f8SGaetan Rivet 
209a46f8d58SGaetan Rivet /* RX / TX */
210a46f8d58SGaetan Rivet 
21186123c2dSStephen Hemminger void failsafe_set_burst_fn(struct rte_eth_dev *dev, int force_safe);
21272a57bfdSGaetan Rivet 
213a46f8d58SGaetan Rivet uint16_t failsafe_rx_burst(void *rxq,
214a46f8d58SGaetan Rivet 		struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
215a46f8d58SGaetan Rivet uint16_t failsafe_tx_burst(void *txq,
216a46f8d58SGaetan Rivet 		struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
217a46f8d58SGaetan Rivet 
21872a57bfdSGaetan Rivet uint16_t failsafe_rx_burst_fast(void *rxq,
21972a57bfdSGaetan Rivet 		struct rte_mbuf **rx_pkts, uint16_t nb_pkts);
22072a57bfdSGaetan Rivet uint16_t failsafe_tx_burst_fast(void *txq,
22172a57bfdSGaetan Rivet 		struct rte_mbuf **tx_pkts, uint16_t nb_pkts);
22272a57bfdSGaetan Rivet 
223a46f8d58SGaetan Rivet /* ARGS */
224a46f8d58SGaetan Rivet 
225a46f8d58SGaetan Rivet int failsafe_args_parse(struct rte_eth_dev *dev, const char *params);
226a46f8d58SGaetan Rivet void failsafe_args_free(struct rte_eth_dev *dev);
227a46f8d58SGaetan Rivet int failsafe_args_count_subdevice(struct rte_eth_dev *dev, const char *params);
228a0194d82SGaetan Rivet int failsafe_args_parse_subs(struct rte_eth_dev *dev);
229a46f8d58SGaetan Rivet 
230a46f8d58SGaetan Rivet /* EAL */
231a46f8d58SGaetan Rivet 
232a46f8d58SGaetan Rivet int failsafe_eal_init(struct rte_eth_dev *dev);
233a46f8d58SGaetan Rivet int failsafe_eal_uninit(struct rte_eth_dev *dev);
234a46f8d58SGaetan Rivet 
235ebea83f8SGaetan Rivet /* ETH_DEV */
236ebea83f8SGaetan Rivet 
237ebea83f8SGaetan Rivet int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev);
2380545c580SMatan Azrad void failsafe_eth_dev_unregister_callbacks(struct sub_device *sdev);
2391a7fa562SThomas Monjalon int failsafe_eth_dev_close(struct rte_eth_dev *dev);
240598fb8aeSGaetan Rivet void failsafe_dev_remove(struct rte_eth_dev *dev);
2416265ab51SMatan Azrad void failsafe_stats_increment(struct rte_eth_stats *to,
2426265ab51SMatan Azrad 				struct rte_eth_stats *from);
243f8244c63SZhiyong Yang int failsafe_eth_rmv_event_callback(uint16_t port_id,
244598fb8aeSGaetan Rivet 				    enum rte_eth_event_type type,
245598fb8aeSGaetan Rivet 				    void *arg, void *out);
246f8244c63SZhiyong Yang int failsafe_eth_lsc_event_callback(uint16_t port_id,
247ad7d6a35SGaetan Rivet 				    enum rte_eth_event_type event,
248ad7d6a35SGaetan Rivet 				    void *cb_arg, void *out);
2497fda13d3SMatan Azrad int failsafe_eth_new_event_callback(uint16_t port_id,
2507fda13d3SMatan Azrad 				    enum rte_eth_event_type event,
2517fda13d3SMatan Azrad 				    void *cb_arg, void *out);
252ebea83f8SGaetan Rivet 
253a46f8d58SGaetan Rivet /* GLOBALS */
254a46f8d58SGaetan Rivet 
255a46f8d58SGaetan Rivet extern const char pmd_failsafe_driver_name[];
256a46f8d58SGaetan Rivet extern const struct eth_dev_ops failsafe_ops;
257b737a1eeSGaetan Rivet extern const struct rte_flow_ops fs_flow_ops;
258520dd992SFerruh Yigit extern uint64_t failsafe_hotplug_poll;
259520dd992SFerruh Yigit extern int failsafe_mac_from_arg;
260a46f8d58SGaetan Rivet 
261a46f8d58SGaetan Rivet /* HELPERS */
262a46f8d58SGaetan Rivet 
263a46f8d58SGaetan Rivet /* dev: (struct rte_eth_dev *) fail-safe device */
264a46f8d58SGaetan Rivet #define PRIV(dev) \
265a46f8d58SGaetan Rivet 	((struct fs_priv *)(dev)->data->dev_private)
266a46f8d58SGaetan Rivet 
267a46f8d58SGaetan Rivet /* sdev: (struct sub_device *) */
268a46f8d58SGaetan Rivet #define ETH(sdev) \
2692f4b9983SRaslan Darawsheh 	((sdev)->sdev_port_id == RTE_MAX_ETHPORTS ? \
2702f4b9983SRaslan Darawsheh 	NULL : &rte_eth_devices[(sdev)->sdev_port_id])
271a46f8d58SGaetan Rivet 
272a46f8d58SGaetan Rivet /* sdev: (struct sub_device *) */
273a46f8d58SGaetan Rivet #define PORT_ID(sdev) \
2742f4b9983SRaslan Darawsheh 	((sdev)->sdev_port_id)
275a46f8d58SGaetan Rivet 
276b737a1eeSGaetan Rivet /* sdev: (struct sub_device *) */
277b737a1eeSGaetan Rivet #define SUB_ID(sdev) \
278b737a1eeSGaetan Rivet 	((sdev)->sid)
279b737a1eeSGaetan Rivet 
280a46f8d58SGaetan Rivet /**
281a46f8d58SGaetan Rivet  * Stateful iterator construct over fail-safe sub-devices:
282a46f8d58SGaetan Rivet  * s:     (struct sub_device *), iterator
283a46f8d58SGaetan Rivet  * i:     (uint8_t), increment
284a46f8d58SGaetan Rivet  * dev:   (struct rte_eth_dev *), fail-safe ethdev
285a46f8d58SGaetan Rivet  * state: (enum dev_state), minimum acceptable device state
286a46f8d58SGaetan Rivet  */
287a46f8d58SGaetan Rivet #define FOREACH_SUBDEV_STATE(s, i, dev, state)		\
288495ca788SGaetan Rivet 	for (s = fs_find_next((dev), 0, state, &i);	\
289495ca788SGaetan Rivet 	     s != NULL;					\
290495ca788SGaetan Rivet 	     s = fs_find_next((dev), i + 1, state, &i))
291a46f8d58SGaetan Rivet 
292a46f8d58SGaetan Rivet /**
293a46f8d58SGaetan Rivet  * Iterator construct over fail-safe sub-devices:
294a46f8d58SGaetan Rivet  * s:   (struct sub_device *), iterator
295a46f8d58SGaetan Rivet  * i:   (uint8_t), increment
296a46f8d58SGaetan Rivet  * dev: (struct rte_eth_dev *), fail-safe ethdev
297a46f8d58SGaetan Rivet  */
298a46f8d58SGaetan Rivet #define FOREACH_SUBDEV(s, i, dev)			\
299a46f8d58SGaetan Rivet 	FOREACH_SUBDEV_STATE(s, i, dev, DEV_UNDEFINED)
300a46f8d58SGaetan Rivet 
301a46f8d58SGaetan Rivet /* dev: (struct rte_eth_dev *) fail-safe device */
302a46f8d58SGaetan Rivet #define PREFERRED_SUBDEV(dev) \
303a46f8d58SGaetan Rivet 	(&PRIV(dev)->subs[0])
304a46f8d58SGaetan Rivet 
305a46f8d58SGaetan Rivet /* dev: (struct rte_eth_dev *) fail-safe device */
306a46f8d58SGaetan Rivet #define TX_SUBDEV(dev)							  \
307a46f8d58SGaetan Rivet 	(PRIV(dev)->subs_tx >= PRIV(dev)->subs_tail		   ? NULL \
308a46f8d58SGaetan Rivet 	 : (PRIV(dev)->subs[PRIV(dev)->subs_tx].state < DEV_PROBED ? NULL \
309a46f8d58SGaetan Rivet 	 : &PRIV(dev)->subs[PRIV(dev)->subs_tx]))
310a46f8d58SGaetan Rivet 
311a46f8d58SGaetan Rivet /**
312a46f8d58SGaetan Rivet  * s:   (struct sub_device *)
313a46f8d58SGaetan Rivet  * ops: (struct eth_dev_ops) member
314a46f8d58SGaetan Rivet  */
315a46f8d58SGaetan Rivet #define SUBOPS(s, ops) \
316a46f8d58SGaetan Rivet 	(ETH(s)->dev_ops->ops)
317a46f8d58SGaetan Rivet 
318598fb8aeSGaetan Rivet /**
319598fb8aeSGaetan Rivet  * Atomic guard
320598fb8aeSGaetan Rivet  */
321598fb8aeSGaetan Rivet 
322598fb8aeSGaetan Rivet /**
323598fb8aeSGaetan Rivet  * a: (rte_atomic64_t)
324598fb8aeSGaetan Rivet  */
325598fb8aeSGaetan Rivet #define FS_ATOMIC_P(a) \
3261e2670a9SMatan Azrad 	rte_atomic64_set(&(a), 1)
327598fb8aeSGaetan Rivet 
328598fb8aeSGaetan Rivet /**
329598fb8aeSGaetan Rivet  * a: (rte_atomic64_t)
330598fb8aeSGaetan Rivet  */
331598fb8aeSGaetan Rivet #define FS_ATOMIC_V(a) \
3321e2670a9SMatan Azrad 	rte_atomic64_set(&(a), 0)
333598fb8aeSGaetan Rivet 
334598fb8aeSGaetan Rivet /**
335598fb8aeSGaetan Rivet  * s: (struct sub_device *)
336598fb8aeSGaetan Rivet  * i: uint16_t qid
337598fb8aeSGaetan Rivet  */
338598fb8aeSGaetan Rivet #define FS_ATOMIC_RX(s, i) \
339598fb8aeSGaetan Rivet 	rte_atomic64_read( \
340fa7bb47aSRaslan Darawsheh 	 &((struct rxq *) \
341fa7bb47aSRaslan Darawsheh 	 (fs_dev(s)->data->rx_queues[i]))->refcnt[(s)->sid])
342598fb8aeSGaetan Rivet /**
343598fb8aeSGaetan Rivet  * s: (struct sub_device *)
344598fb8aeSGaetan Rivet  * i: uint16_t qid
345598fb8aeSGaetan Rivet  */
346598fb8aeSGaetan Rivet #define FS_ATOMIC_TX(s, i) \
347598fb8aeSGaetan Rivet 	rte_atomic64_read( \
348fa7bb47aSRaslan Darawsheh 	 &((struct txq *) \
349fa7bb47aSRaslan Darawsheh 	 (fs_dev(s)->data->tx_queues[i]))->refcnt[(s)->sid])
350598fb8aeSGaetan Rivet 
3515fbc1d49SBruce Richardson #ifdef RTE_EXEC_ENV_FREEBSD
3523344fb8fSThomas Monjalon #define FS_THREADID_TYPE void*
3533344fb8fSThomas Monjalon #define FS_THREADID_FMT  "p"
3543344fb8fSThomas Monjalon #else
3553344fb8fSThomas Monjalon #define FS_THREADID_TYPE unsigned long
3563344fb8fSThomas Monjalon #define FS_THREADID_FMT  "lu"
3573344fb8fSThomas Monjalon #endif
3583344fb8fSThomas Monjalon 
359ebeb72ecSStephen Hemminger extern int failsafe_logtype;
360*2b843cacSDavid Marchand #define RTE_LOGTYPE_NET_FAILSAFE failsafe_logtype
361ebeb72ecSStephen Hemminger 
362*2b843cacSDavid Marchand #define LOG_(l, ...) RTE_LOG_LINE(l, NET_FAILSAFE, __VA_ARGS__)
363a46f8d58SGaetan Rivet #define DEBUG(...) LOG_(DEBUG, __VA_ARGS__)
364a46f8d58SGaetan Rivet #define INFO(...) LOG_(INFO, __VA_ARGS__)
365a46f8d58SGaetan Rivet #define WARN(...) LOG_(WARNING, __VA_ARGS__)
366a46f8d58SGaetan Rivet #define ERROR(...) LOG_(ERR, __VA_ARGS__)
367a46f8d58SGaetan Rivet 
368a46f8d58SGaetan Rivet /* inlined functions */
369a46f8d58SGaetan Rivet 
370495ca788SGaetan Rivet static inline struct sub_device *
371495ca788SGaetan Rivet fs_find_next(struct rte_eth_dev *dev,
372495ca788SGaetan Rivet 	     uint8_t sid,
373495ca788SGaetan Rivet 	     enum dev_state min_state,
374495ca788SGaetan Rivet 	     uint8_t *sid_out)
375a46f8d58SGaetan Rivet {
376495ca788SGaetan Rivet 	struct sub_device *subs;
377495ca788SGaetan Rivet 	uint8_t tail;
378495ca788SGaetan Rivet 
379495ca788SGaetan Rivet 	subs = PRIV(dev)->subs;
380495ca788SGaetan Rivet 	tail = PRIV(dev)->subs_tail;
381495ca788SGaetan Rivet 	while (sid < tail) {
382495ca788SGaetan Rivet 		if (subs[sid].state >= min_state)
383a46f8d58SGaetan Rivet 			break;
384a46f8d58SGaetan Rivet 		sid++;
385a46f8d58SGaetan Rivet 	}
386495ca788SGaetan Rivet 	*sid_out = sid;
387495ca788SGaetan Rivet 	if (sid >= tail)
388495ca788SGaetan Rivet 		return NULL;
389495ca788SGaetan Rivet 	return &subs[sid];
390a46f8d58SGaetan Rivet }
391a46f8d58SGaetan Rivet 
392fa7bb47aSRaslan Darawsheh static inline struct rte_eth_dev *
393fa7bb47aSRaslan Darawsheh fs_dev(struct sub_device *sdev) {
394fa7bb47aSRaslan Darawsheh 	return &rte_eth_devices[sdev->fs_port_id];
395fa7bb47aSRaslan Darawsheh }
396fa7bb47aSRaslan Darawsheh 
397598fb8aeSGaetan Rivet /*
398655fcd68SMatan Azrad  * Lock hot-plug mutex.
399655fcd68SMatan Azrad  * is_alarm means that the caller is, for sure, the hot-plug alarm mechanism.
400655fcd68SMatan Azrad  */
401655fcd68SMatan Azrad static inline int
402655fcd68SMatan Azrad fs_lock(struct rte_eth_dev *dev, unsigned int is_alarm)
403655fcd68SMatan Azrad {
404655fcd68SMatan Azrad 	int ret;
405655fcd68SMatan Azrad 
406655fcd68SMatan Azrad 	if (is_alarm) {
407655fcd68SMatan Azrad 		ret = pthread_mutex_trylock(&PRIV(dev)->hotplug_mutex);
408655fcd68SMatan Azrad 		if (ret) {
409655fcd68SMatan Azrad 			DEBUG("Hot-plug mutex lock trying failed(%s), will try"
410655fcd68SMatan Azrad 			      " again later...", strerror(ret));
411655fcd68SMatan Azrad 			return ret;
412655fcd68SMatan Azrad 		}
413655fcd68SMatan Azrad 		PRIV(dev)->alarm_lock = 1;
414655fcd68SMatan Azrad 	} else {
415655fcd68SMatan Azrad 		ret = pthread_mutex_lock(&PRIV(dev)->hotplug_mutex);
416655fcd68SMatan Azrad 		if (ret) {
417655fcd68SMatan Azrad 			ERROR("Cannot lock mutex(%s)", strerror(ret));
418655fcd68SMatan Azrad 			return ret;
419655fcd68SMatan Azrad 		}
420655fcd68SMatan Azrad 	}
421655fcd68SMatan Azrad 	return ret;
422655fcd68SMatan Azrad }
423655fcd68SMatan Azrad 
424655fcd68SMatan Azrad /*
425655fcd68SMatan Azrad  * Unlock hot-plug mutex.
426655fcd68SMatan Azrad  * is_alarm means that the caller is, for sure, the hot-plug alarm mechanism.
427655fcd68SMatan Azrad  */
428655fcd68SMatan Azrad static inline void
429655fcd68SMatan Azrad fs_unlock(struct rte_eth_dev *dev, unsigned int is_alarm)
430655fcd68SMatan Azrad {
431655fcd68SMatan Azrad 	int ret;
432655fcd68SMatan Azrad 
433655fcd68SMatan Azrad 	if (is_alarm) {
434655fcd68SMatan Azrad 		RTE_ASSERT(PRIV(dev)->alarm_lock == 1);
435655fcd68SMatan Azrad 		PRIV(dev)->alarm_lock = 0;
436655fcd68SMatan Azrad 	}
437655fcd68SMatan Azrad 	ret = pthread_mutex_unlock(&PRIV(dev)->hotplug_mutex);
438655fcd68SMatan Azrad 	if (ret)
439655fcd68SMatan Azrad 		ERROR("Cannot unlock hot-plug mutex(%s)", strerror(ret));
440655fcd68SMatan Azrad }
441655fcd68SMatan Azrad 
442655fcd68SMatan Azrad /*
443598fb8aeSGaetan Rivet  * Switch emitting device.
444598fb8aeSGaetan Rivet  * If banned is set, banned must not be considered for
445598fb8aeSGaetan Rivet  * the role of emitting device.
446598fb8aeSGaetan Rivet  */
447ebea83f8SGaetan Rivet static inline void
448598fb8aeSGaetan Rivet fs_switch_dev(struct rte_eth_dev *dev,
449598fb8aeSGaetan Rivet 	      struct sub_device *banned)
450ebea83f8SGaetan Rivet {
451598fb8aeSGaetan Rivet 	struct sub_device *txd;
452ebea83f8SGaetan Rivet 	enum dev_state req_state;
453ebea83f8SGaetan Rivet 
454ebea83f8SGaetan Rivet 	req_state = PRIV(dev)->state;
455598fb8aeSGaetan Rivet 	txd = TX_SUBDEV(dev);
456598fb8aeSGaetan Rivet 	if (PREFERRED_SUBDEV(dev)->state >= req_state &&
457598fb8aeSGaetan Rivet 	    PREFERRED_SUBDEV(dev) != banned) {
458598fb8aeSGaetan Rivet 		if (txd != PREFERRED_SUBDEV(dev) &&
459598fb8aeSGaetan Rivet 		    (txd == NULL ||
460ebea83f8SGaetan Rivet 		     (req_state == DEV_STARTED) ||
461598fb8aeSGaetan Rivet 		     (txd && txd->state < DEV_STARTED))) {
462ebea83f8SGaetan Rivet 			DEBUG("Switching tx_dev to preferred sub_device");
463ebea83f8SGaetan Rivet 			PRIV(dev)->subs_tx = 0;
464ebea83f8SGaetan Rivet 		}
465598fb8aeSGaetan Rivet 	} else if ((txd && txd->state < req_state) ||
466598fb8aeSGaetan Rivet 		   txd == NULL ||
467598fb8aeSGaetan Rivet 		   txd == banned) {
468d8d89966SMatan Azrad 		struct sub_device *sdev = NULL;
469ebea83f8SGaetan Rivet 		uint8_t i;
470ebea83f8SGaetan Rivet 
471ebea83f8SGaetan Rivet 		/* Using acceptable device */
472ebea83f8SGaetan Rivet 		FOREACH_SUBDEV_STATE(sdev, i, dev, req_state) {
473598fb8aeSGaetan Rivet 			if (sdev == banned)
474598fb8aeSGaetan Rivet 				continue;
475ebea83f8SGaetan Rivet 			DEBUG("Switching tx_dev to sub_device %d",
476ebea83f8SGaetan Rivet 			      i);
477ebea83f8SGaetan Rivet 			PRIV(dev)->subs_tx = i;
478ebea83f8SGaetan Rivet 			break;
479ebea83f8SGaetan Rivet 		}
480d8d89966SMatan Azrad 		if (i >= PRIV(dev)->subs_tail || sdev == NULL) {
481ebea83f8SGaetan Rivet 			DEBUG("No device ready, deactivating tx_dev");
482ebea83f8SGaetan Rivet 			PRIV(dev)->subs_tx = PRIV(dev)->subs_tail;
483d8d89966SMatan Azrad 		}
484ebea83f8SGaetan Rivet 	} else {
485ebea83f8SGaetan Rivet 		return;
486ebea83f8SGaetan Rivet 	}
48786123c2dSStephen Hemminger 	failsafe_set_burst_fn(dev, 0);
488ebea83f8SGaetan Rivet 	rte_wmb();
489ebea83f8SGaetan Rivet }
490ebea83f8SGaetan Rivet 
491ae80146cSMatan Azrad /*
492ae80146cSMatan Azrad  * Adjust error value and rte_errno to the fail-safe actual error value.
493ae80146cSMatan Azrad  */
494ae80146cSMatan Azrad static inline int
495ae80146cSMatan Azrad fs_err(struct sub_device *sdev, int err)
496ae80146cSMatan Azrad {
497ae80146cSMatan Azrad 	/* A device removal shouldn't be reported as an error. */
498ae80146cSMatan Azrad 	if (sdev->remove == 1 || err == -EIO)
499ae80146cSMatan Azrad 		return rte_errno = 0;
500ae80146cSMatan Azrad 	return err;
501ae80146cSMatan Azrad }
502b28f28aeSDharmik Thakkar #endif /* _ETH_FAILSAFE_PRIVATE_H_ */
503