/* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (C) 2018-2021, Intel Corporation. */ #ifndef _ICE_LAG_H_ #define _ICE_LAG_H_ #include /* LAG roles for netdev */ enum ice_lag_role { ICE_LAG_NONE, ICE_LAG_PRIMARY, ICE_LAG_BACKUP, ICE_LAG_UNSET }; struct ice_pf; /* LAG info struct */ struct ice_lag { struct ice_pf *pf; /* backlink to PF struct */ struct net_device *netdev; /* this PF's netdev */ struct net_device *peer_netdev; struct net_device *upper_netdev; /* upper bonding netdev */ struct notifier_block notif_block; u8 bonded:1; /* currently bonded */ u8 master:1; /* this is a master */ u8 handler:1; /* did we register a rx_netdev_handler */ /* each thing blocking bonding will increment this value by one. * If this value is zero, then bonding is allowed. */ u16 dis_lag; u8 role; }; int ice_init_lag(struct ice_pf *pf); void ice_deinit_lag(struct ice_pf *pf); rx_handler_result_t ice_lag_nop_handler(struct sk_buff **pskb); /** * ice_disable_lag - increment LAG disable count * @lag: LAG struct */ static inline void ice_disable_lag(struct ice_lag *lag) { /* If LAG this PF is not already disabled, disable it */ rtnl_lock(); if (!netdev_is_rx_handler_busy(lag->netdev)) { if (!netdev_rx_handler_register(lag->netdev, ice_lag_nop_handler, NULL)) lag->handler = true; } rtnl_unlock(); lag->dis_lag++; } /** * ice_enable_lag - decrement disable count for a PF * @lag: LAG struct * * Decrement the disable counter for a port, and if that count reaches * zero, then remove the no-op Rx handler from that netdev */ static inline void ice_enable_lag(struct ice_lag *lag) { if (lag->dis_lag) lag->dis_lag--; if (!lag->dis_lag && lag->handler) { rtnl_lock(); netdev_rx_handler_unregister(lag->netdev); rtnl_unlock(); lag->handler = false; } } /** * ice_is_lag_dis - is LAG disabled * @lag: LAG struct * * Return true if bonding is disabled */ static inline bool ice_is_lag_dis(struct ice_lag *lag) { return !!(lag->dis_lag); } #endif /* _ICE_LAG_H_ */