@@ -21,6 +21,24 @@ enum {
2121 MLO_AN_FIXED , /* Fixed-link mode */
2222 MLO_AN_INBAND , /* In-band protocol */
2323
24+ /* PCS "negotiation" mode.
25+ * PHYLINK_PCS_NEG_NONE - protocol has no inband capability
26+ * PHYLINK_PCS_NEG_OUTBAND - some out of band or fixed link setting
27+ * PHYLINK_PCS_NEG_INBAND_DISABLED - inband mode disabled, e.g.
28+ * 1000base-X with autoneg off
29+ * PHYLINK_PCS_NEG_INBAND_ENABLED - inband mode enabled
30+ * Additionally, this can be tested using bitmasks:
31+ * PHYLINK_PCS_NEG_INBAND - inband mode selected
32+ * PHYLINK_PCS_NEG_ENABLED - negotiation mode enabled
33+ */
34+ PHYLINK_PCS_NEG_NONE = 0 ,
35+ PHYLINK_PCS_NEG_ENABLED = BIT (4 ),
36+ PHYLINK_PCS_NEG_OUTBAND = BIT (5 ),
37+ PHYLINK_PCS_NEG_INBAND = BIT (6 ),
38+ PHYLINK_PCS_NEG_INBAND_DISABLED = PHYLINK_PCS_NEG_INBAND ,
39+ PHYLINK_PCS_NEG_INBAND_ENABLED = PHYLINK_PCS_NEG_INBAND |
40+ PHYLINK_PCS_NEG_ENABLED ,
41+
2442 /* MAC_SYM_PAUSE and MAC_ASYM_PAUSE are used when configuring our
2543 * autonegotiation advertisement. They correspond to the PAUSE and
2644 * ASM_DIR bits defined by 802.3, respectively.
@@ -79,6 +97,70 @@ static inline bool phylink_autoneg_inband(unsigned int mode)
7997 return mode == MLO_AN_INBAND ;
8098}
8199
100+ /**
101+ * phylink_pcs_neg_mode() - helper to determine PCS inband mode
102+ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
103+ * @interface: interface mode to be used
104+ * @advertising: adertisement ethtool link mode mask
105+ *
106+ * Determines the negotiation mode to be used by the PCS, and returns
107+ * one of:
108+ * %PHYLINK_PCS_NEG_NONE: interface mode does not support inband
109+ * %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY)
110+ * will be used.
111+ * %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg disabled
112+ * %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled
113+ *
114+ * Note: this is for cases where the PCS itself is involved in negotiation
115+ * (e.g. Clause 37, SGMII and similar) not Clause 73.
116+ */
117+ static inline unsigned int phylink_pcs_neg_mode (unsigned int mode ,
118+ phy_interface_t interface ,
119+ const unsigned long * advertising )
120+ {
121+ unsigned int neg_mode ;
122+
123+ switch (interface ) {
124+ case PHY_INTERFACE_MODE_SGMII :
125+ case PHY_INTERFACE_MODE_QSGMII :
126+ case PHY_INTERFACE_MODE_QUSGMII :
127+ case PHY_INTERFACE_MODE_USXGMII :
128+ /* These protocols are designed for use with a PHY which
129+ * communicates its negotiation result back to the MAC via
130+ * inband communication. Note: there exist PHYs that run
131+ * with SGMII but do not send the inband data.
132+ */
133+ if (!phylink_autoneg_inband (mode ))
134+ neg_mode = PHYLINK_PCS_NEG_OUTBAND ;
135+ else
136+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
137+ break ;
138+
139+ case PHY_INTERFACE_MODE_1000BASEX :
140+ case PHY_INTERFACE_MODE_2500BASEX :
141+ /* 1000base-X is designed for use media-side for Fibre
142+ * connections, and thus the Autoneg bit needs to be
143+ * taken into account. We also do this for 2500base-X
144+ * as well, but drivers may not support this, so may
145+ * need to override this.
146+ */
147+ if (!phylink_autoneg_inband (mode ))
148+ neg_mode = PHYLINK_PCS_NEG_OUTBAND ;
149+ else if (linkmode_test_bit (ETHTOOL_LINK_MODE_Autoneg_BIT ,
150+ advertising ))
151+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED ;
152+ else
153+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED ;
154+ break ;
155+
156+ default :
157+ neg_mode = PHYLINK_PCS_NEG_NONE ;
158+ break ;
159+ }
160+
161+ return neg_mode ;
162+ }
163+
82164/**
83165 * struct phylink_link_state - link state structure
84166 * @advertising: ethtool bitmask containing advertised link modes
@@ -436,13 +518,15 @@ struct phylink_pcs_ops;
436518/**
437519 * struct phylink_pcs - PHYLINK PCS instance
438520 * @ops: a pointer to the &struct phylink_pcs_ops structure
521+ * @neg_mode: provide PCS neg mode via "mode" argument
439522 * @poll: poll the PCS for link changes
440523 *
441524 * This structure is designed to be embedded within the PCS private data,
442525 * and will be passed between phylink and the PCS.
443526 */
444527struct phylink_pcs {
445528 const struct phylink_pcs_ops * ops ;
529+ bool neg_mode ;
446530 bool poll ;
447531};
448532
@@ -460,12 +544,12 @@ struct phylink_pcs_ops {
460544 const struct phylink_link_state * state );
461545 void (* pcs_get_state )(struct phylink_pcs * pcs ,
462546 struct phylink_link_state * state );
463- int (* pcs_config )(struct phylink_pcs * pcs , unsigned int mode ,
547+ int (* pcs_config )(struct phylink_pcs * pcs , unsigned int neg_mode ,
464548 phy_interface_t interface ,
465549 const unsigned long * advertising ,
466550 bool permit_pause_to_mac );
467551 void (* pcs_an_restart )(struct phylink_pcs * pcs );
468- void (* pcs_link_up )(struct phylink_pcs * pcs , unsigned int mode ,
552+ void (* pcs_link_up )(struct phylink_pcs * pcs , unsigned int neg_mode ,
469553 phy_interface_t interface , int speed , int duplex );
470554};
471555
@@ -508,7 +592,7 @@ void pcs_get_state(struct phylink_pcs *pcs,
508592/**
509593 * pcs_config() - Configure the PCS mode and advertisement
510594 * @pcs: a pointer to a &struct phylink_pcs.
511- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
595+ * @neg_mode: link negotiation mode (see below)
512596 * @interface: interface mode to be used
513597 * @advertising: adertisement ethtool link mode mask
514598 * @permit_pause_to_mac: permit forwarding pause resolution to MAC
@@ -526,8 +610,12 @@ void pcs_get_state(struct phylink_pcs *pcs,
526610 * For 1000BASE-X, the advertisement should be programmed into the PCS.
527611 *
528612 * For most 10GBASE-R, there is no advertisement.
613+ *
614+ * The %neg_mode argument should be tested via the phylink_mode_*() family of
615+ * functions, or for PCS that set pcs->neg_mode true, should be tested
616+ * against the %PHYLINK_PCS_NEG_* definitions.
529617 */
530- int pcs_config (struct phylink_pcs * pcs , unsigned int mode ,
618+ int pcs_config (struct phylink_pcs * pcs , unsigned int neg_mode ,
531619 phy_interface_t interface , const unsigned long * advertising ,
532620 bool permit_pause_to_mac );
533621
@@ -543,7 +631,7 @@ void pcs_an_restart(struct phylink_pcs *pcs);
543631/**
544632 * pcs_link_up() - program the PCS for the resolved link configuration
545633 * @pcs: a pointer to a &struct phylink_pcs.
546- * @mode : link autonegotiation mode
634+ * @neg_mode : link negotiation mode (see below)
547635 * @interface: link &typedef phy_interface_t mode
548636 * @speed: link speed
549637 * @duplex: link duplex
@@ -552,8 +640,12 @@ void pcs_an_restart(struct phylink_pcs *pcs);
552640 * the resolved link parameters. For example, a PCS operating in SGMII
553641 * mode without in-band AN needs to be manually configured for the link
554642 * and duplex setting. Otherwise, this should be a no-op.
643+ *
644+ * The %mode argument should be tested via the phylink_mode_*() family of
645+ * functions, or for PCS that set pcs->neg_mode true, should be tested
646+ * against the %PHYLINK_PCS_NEG_* definitions.
555647 */
556- void pcs_link_up (struct phylink_pcs * pcs , unsigned int mode ,
648+ void pcs_link_up (struct phylink_pcs * pcs , unsigned int neg_mode ,
557649 phy_interface_t interface , int speed , int duplex );
558650#endif
559651
0 commit comments