summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2020-02-16 19:39:45 -0800
committerDavid S. Miller <davem@davemloft.net>2020-02-16 19:39:45 -0800
commit5652b46e4e802910f5e06ac3ed66ee9853027b34 (patch)
tree15cec65c27269b5f9e95beb54385fd0ee8f7acbe /include/linux
parentce7805513d902c07d8d4266b73b692fbdc66f440 (diff)
parentb70486f94bb4820e84491089da5e30d29e774b0d (diff)
downloadcachepc-linux-5652b46e4e802910f5e06ac3ed66ee9853027b34.tar.gz
cachepc-linux-5652b46e4e802910f5e06ac3ed66ee9853027b34.zip
Merge branch 'Pause-updates-for-phylib-and-phylink'
Russell King says: ==================== Pause updates for phylib and phylink Currently, phylib resolves the speed and duplex settings, which MAC drivers use directly. phylib also extracts the "Pause" and "AsymPause" bits from the link partner's advertisement, and stores them in struct phy_device's pause and asym_pause members with no further processing. It is left up to each MAC driver to implement decoding for this information. phylink converted drivers are able to take advantage of code therein which resolves the pause advertisements for the MAC driver, but this does nothing for unconverted drivers. It also does not allow us to make use of hardware-resolved pause states offered by several PHYs. This series aims to address this by: 1. Providing a generic implementation, linkmode_resolve_pause(), that takes the ethtool linkmode arrays for the link partner and local advertisements, decoding the result to whether pause frames should be allowed to be transmitted or received and acted upon. I call this the pause enablement state. 2. Providing a phylib implementation, phy_get_pause(), which allows MAC drivers to request the pause enablement state from phylib. 3. Providing a generic linkmode_set_pause() for setting the pause advertisement according to the ethtool tx/rx flags - note that this design has some shortcomings, see the comments in the kerneldoc for this function. 4. Remove the ability in phylink to set the pause states for fixed links, which brings them into line with how we deal with the speed and duplex parameters; we can reintroduce this later if anyone requires it. This could be a userspace-visible change. 5. Split application of manual pause enablement state from phylink's resolution of the same to allow use of phylib's new phy_get_pause() interface by phylink, and make that switch. 6. Resolve the fixed-link pause enablement state using the generic linkmode_resolve_pause() helper introduced earlier. This, in connection with the previous commits, allows us to kill the MLO_PAUSE_SYM and MLO_PAUSE_ASYM flags. 7. make phylink's ethtool pause setting implementation update the pause advertisement in the same way that phylib does, with the same caveats that are present there (as mentioned above w.r.t linkmode_set_pause()). 8. create a more accurate initial configuration for MACs, used when phy_start() is called or a SFP is detected. In particular, this ensures that the pause bits seen by MAC drivers in state->pause are accurate for SGMII. 9. finally, update the kerneldoc descriptions for mac_config() for the above changes. This series has been build-tested against net-next; the boot tested patches are in my "phy" branch against v5.5 plus the queued phylink changes that were merged for 5.6. The next series will introduce the ability for phylib drivers to provide hardware resolved pause enablement state. These patches can be found in my "phy" branch. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/linkmode.h8
-rw-r--r--include/linux/phy.h3
-rw-r--r--include/linux/phylink.h34
3 files changed, 31 insertions, 14 deletions
diff --git a/include/linux/linkmode.h b/include/linux/linkmode.h
index fe740031339d..c664c27a29a0 100644
--- a/include/linux/linkmode.h
+++ b/include/linux/linkmode.h
@@ -71,7 +71,7 @@ static inline void linkmode_change_bit(int nr, volatile unsigned long *addr)
__change_bit(nr, addr);
}
-static inline int linkmode_test_bit(int nr, volatile unsigned long *addr)
+static inline int linkmode_test_bit(int nr, const volatile unsigned long *addr)
{
return test_bit(nr, addr);
}
@@ -88,4 +88,10 @@ static inline int linkmode_subset(const unsigned long *src1,
return bitmap_subset(src1, src2, __ETHTOOL_LINK_MODE_MASK_NBITS);
}
+void linkmode_resolve_pause(const unsigned long *local_adv,
+ const unsigned long *partner_adv,
+ bool *tx_pause, bool *rx_pause);
+
+void linkmode_set_pause(unsigned long *advertisement, bool tx, bool rx);
+
#endif /* __LINKMODE_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index c570e162e05e..80f8b2158271 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1257,6 +1257,9 @@ void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx,
void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx);
bool phy_validate_pause(struct phy_device *phydev,
struct ethtool_pauseparam *pp);
+void phy_get_pause(struct phy_device *phydev, bool *tx_pause, bool *rx_pause);
+void phy_resolve_pause(unsigned long *local_adv, unsigned long *partner_adv,
+ bool *tx_pause, bool *rx_pause);
int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *));
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 523209e70947..812357c03df4 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -12,12 +12,10 @@ struct net_device;
enum {
MLO_PAUSE_NONE,
- MLO_PAUSE_ASYM = BIT(0),
- MLO_PAUSE_SYM = BIT(1),
- MLO_PAUSE_RX = BIT(2),
- MLO_PAUSE_TX = BIT(3),
+ MLO_PAUSE_RX = BIT(0),
+ MLO_PAUSE_TX = BIT(1),
MLO_PAUSE_TXRX_MASK = MLO_PAUSE_TX | MLO_PAUSE_RX,
- MLO_PAUSE_AN = BIT(4),
+ MLO_PAUSE_AN = BIT(2),
MLO_AN_PHY = 0, /* Conventional PHY */
MLO_AN_FIXED, /* Fixed-link mode */
@@ -154,13 +152,20 @@ void mac_pcs_get_state(struct phylink_config *config,
* guaranteed to be correct, and so any mac_config() implementation must
* never reference these fields.
*
+ * In all negotiation modes, as defined by @mode, @state->pause indicates the
+ * pause settings which should be applied as follows. If %MLO_PAUSE_AN is not
+ * set, %MLO_PAUSE_TX and %MLO_PAUSE_RX indicate whether the MAC should send
+ * pause frames and/or act on received pause frames respectively. Otherwise,
+ * the results of in-band negotiation/status from the MAC PCS should be used
+ * to control the MAC pause mode settings.
+ *
* The action performed depends on the currently selected mode:
*
* %MLO_AN_FIXED, %MLO_AN_PHY:
- * Configure the specified @state->speed, @state->duplex and
- * @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) modes over a link
- * specified by @state->interface. @state->advertising may be used,
- * but is not required. Other members of @state must be ignored.
+ * Configure the specified @state->speed and @state->duplex over a link
+ * specified by @state->interface. @state->advertising may be used, but
+ * is not required. Pause modes as above. Other members of @state must
+ * be ignored.
*
* Valid state members: interface, speed, duplex, pause, advertising.
*
@@ -172,11 +177,14 @@ void mac_pcs_get_state(struct phylink_config *config,
* mac_pcs_get_state() callback. Changes in link state must be made
* by calling phylink_mac_change().
*
+ * Interface mode specific details are mentioned below.
+ *
* If in 802.3z mode, the link speed is fixed, dependent on the
- * @state->interface. Duplex is negotiated, and pause is advertised
- * according to @state->an_enabled, @state->pause and
- * @state->advertising flags. Beware of MACs which only support full
- * duplex at gigabit and higher speeds.
+ * @state->interface. Duplex and pause modes are negotiated via
+ * the in-band configuration word. Advertised pause modes are set
+ * according to the @state->an_enabled and @state->advertising
+ * flags. Beware of MACs which only support full duplex at gigabit
+ * and higher speeds.
*
* If in Cisco SGMII mode, the link speed and duplex mode are passed
* in the serial bitstream 16-bit configuration word, and the MAC