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