![]() |
|
|||
0001 // SPDX-License-Identifier: GPL-2.0+ 0002 #include <linux/linkmode.h> 0003 0004 /** 0005 * linkmode_resolve_pause - resolve the allowable pause modes 0006 * @local_adv: local advertisement in ethtool format 0007 * @partner_adv: partner advertisement in ethtool format 0008 * @tx_pause: pointer to bool to indicate whether transmit pause should be 0009 * enabled. 0010 * @rx_pause: pointer to bool to indicate whether receive pause should be 0011 * enabled. 0012 * 0013 * Flow control is resolved according to our and the link partners 0014 * advertisements using the following drawn from the 802.3 specs: 0015 * Local device Link partner 0016 * Pause AsymDir Pause AsymDir Result 0017 * 0 X 0 X Disabled 0018 * 0 1 1 0 Disabled 0019 * 0 1 1 1 TX 0020 * 1 0 0 X Disabled 0021 * 1 X 1 X TX+RX 0022 * 1 1 0 1 RX 0023 */ 0024 void linkmode_resolve_pause(const unsigned long *local_adv, 0025 const unsigned long *partner_adv, 0026 bool *tx_pause, bool *rx_pause) 0027 { 0028 __ETHTOOL_DECLARE_LINK_MODE_MASK(m); 0029 0030 linkmode_and(m, local_adv, partner_adv); 0031 if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, m)) { 0032 *tx_pause = true; 0033 *rx_pause = true; 0034 } else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, m)) { 0035 *tx_pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, 0036 partner_adv); 0037 *rx_pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, 0038 local_adv); 0039 } else { 0040 *tx_pause = false; 0041 *rx_pause = false; 0042 } 0043 } 0044 EXPORT_SYMBOL_GPL(linkmode_resolve_pause); 0045 0046 /** 0047 * linkmode_set_pause - set the pause mode advertisement 0048 * @advertisement: advertisement in ethtool format 0049 * @tx: boolean from ethtool struct ethtool_pauseparam tx_pause member 0050 * @rx: boolean from ethtool struct ethtool_pauseparam rx_pause member 0051 * 0052 * Configure the advertised Pause and Asym_Pause bits according to the 0053 * capabilities of provided in @tx and @rx. 0054 * 0055 * We convert as follows: 0056 * tx rx Pause AsymDir 0057 * 0 0 0 0 0058 * 0 1 1 1 0059 * 1 0 0 1 0060 * 1 1 1 0 0061 * 0062 * Note: this translation from ethtool tx/rx notation to the advertisement 0063 * is actually very problematical. Here are some examples: 0064 * 0065 * For tx=0 rx=1, meaning transmit is unsupported, receive is supported: 0066 * 0067 * Local device Link partner 0068 * Pause AsymDir Pause AsymDir Result 0069 * 1 1 1 0 TX + RX - but we have no TX support. 0070 * 1 1 0 1 Only this gives RX only 0071 * 0072 * For tx=1 rx=1, meaning we have the capability to transmit and receive 0073 * pause frames: 0074 * 0075 * Local device Link partner 0076 * Pause AsymDir Pause AsymDir Result 0077 * 1 0 0 1 Disabled - but since we do support tx and rx, 0078 * this should resolve to RX only. 0079 * 0080 * Hence, asking for: 0081 * rx=1 tx=0 gives Pause+AsymDir advertisement, but we may end up 0082 * resolving to tx+rx pause or only rx pause depending on 0083 * the partners advertisement. 0084 * rx=0 tx=1 gives AsymDir only, which will only give tx pause if 0085 * the partners advertisement allows it. 0086 * rx=1 tx=1 gives Pause only, which will only allow tx+rx pause 0087 * if the other end also advertises Pause. 0088 */ 0089 void linkmode_set_pause(unsigned long *advertisement, bool tx, bool rx) 0090 { 0091 linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertisement, rx); 0092 linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertisement, 0093 rx ^ tx); 0094 } 0095 EXPORT_SYMBOL_GPL(linkmode_set_pause);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |