Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * linux/mii.h: definitions for MII-compatible transceivers
0004  * Originally drivers/net/sunhme.h.
0005  *
0006  * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
0007  */
0008 #ifndef __LINUX_MII_H__
0009 #define __LINUX_MII_H__
0010 
0011 
0012 #include <linux/if.h>
0013 #include <linux/linkmode.h>
0014 #include <uapi/linux/mii.h>
0015 
0016 struct ethtool_cmd;
0017 
0018 struct mii_if_info {
0019     int phy_id;
0020     int advertising;
0021     int phy_id_mask;
0022     int reg_num_mask;
0023 
0024     unsigned int full_duplex : 1;   /* is full duplex? */
0025     unsigned int force_media : 1;   /* is autoneg. disabled? */
0026     unsigned int supports_gmii : 1; /* are GMII registers supported? */
0027 
0028     struct net_device *dev;
0029     int (*mdio_read) (struct net_device *dev, int phy_id, int location);
0030     void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
0031 };
0032 
0033 extern int mii_link_ok (struct mii_if_info *mii);
0034 extern int mii_nway_restart (struct mii_if_info *mii);
0035 extern void mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
0036 extern void mii_ethtool_get_link_ksettings(
0037     struct mii_if_info *mii, struct ethtool_link_ksettings *cmd);
0038 extern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
0039 extern int mii_ethtool_set_link_ksettings(
0040     struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd);
0041 extern int mii_check_gmii_support(struct mii_if_info *mii);
0042 extern void mii_check_link (struct mii_if_info *mii);
0043 extern unsigned int mii_check_media (struct mii_if_info *mii,
0044                      unsigned int ok_to_print,
0045                      unsigned int init_media);
0046 extern int generic_mii_ioctl(struct mii_if_info *mii_if,
0047                  struct mii_ioctl_data *mii_data, int cmd,
0048                  unsigned int *duplex_changed);
0049 
0050 
0051 static inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
0052 {
0053     return (struct mii_ioctl_data *) &rq->ifr_ifru;
0054 }
0055 
0056 /**
0057  * mii_nway_result
0058  * @negotiated: value of MII ANAR and'd with ANLPAR
0059  *
0060  * Given a set of MII abilities, check each bit and returns the
0061  * currently supported media, in the priority order defined by
0062  * IEEE 802.3u.  We use LPA_xxx constants but note this is not the
0063  * value of LPA solely, as described above.
0064  *
0065  * The one exception to IEEE 802.3u is that 100baseT4 is placed
0066  * between 100T-full and 100T-half.  If your phy does not support
0067  * 100T4 this is fine.  If your phy places 100T4 elsewhere in the
0068  * priority order, you will need to roll your own function.
0069  */
0070 static inline unsigned int mii_nway_result (unsigned int negotiated)
0071 {
0072     unsigned int ret;
0073 
0074     if (negotiated & LPA_100FULL)
0075         ret = LPA_100FULL;
0076     else if (negotiated & LPA_100BASE4)
0077         ret = LPA_100BASE4;
0078     else if (negotiated & LPA_100HALF)
0079         ret = LPA_100HALF;
0080     else if (negotiated & LPA_10FULL)
0081         ret = LPA_10FULL;
0082     else
0083         ret = LPA_10HALF;
0084 
0085     return ret;
0086 }
0087 
0088 /**
0089  * mii_duplex
0090  * @duplex_lock: Non-zero if duplex is locked at full
0091  * @negotiated: value of MII ANAR and'd with ANLPAR
0092  *
0093  * A small helper function for a common case.  Returns one
0094  * if the media is operating or locked at full duplex, and
0095  * returns zero otherwise.
0096  */
0097 static inline unsigned int mii_duplex (unsigned int duplex_lock,
0098                        unsigned int negotiated)
0099 {
0100     if (duplex_lock)
0101         return 1;
0102     if (mii_nway_result(negotiated) & LPA_DUPLEX)
0103         return 1;
0104     return 0;
0105 }
0106 
0107 /**
0108  * ethtool_adv_to_mii_adv_t
0109  * @ethadv: the ethtool advertisement settings
0110  *
0111  * A small helper function that translates ethtool advertisement
0112  * settings to phy autonegotiation advertisements for the
0113  * MII_ADVERTISE register.
0114  */
0115 static inline u32 ethtool_adv_to_mii_adv_t(u32 ethadv)
0116 {
0117     u32 result = 0;
0118 
0119     if (ethadv & ADVERTISED_10baseT_Half)
0120         result |= ADVERTISE_10HALF;
0121     if (ethadv & ADVERTISED_10baseT_Full)
0122         result |= ADVERTISE_10FULL;
0123     if (ethadv & ADVERTISED_100baseT_Half)
0124         result |= ADVERTISE_100HALF;
0125     if (ethadv & ADVERTISED_100baseT_Full)
0126         result |= ADVERTISE_100FULL;
0127     if (ethadv & ADVERTISED_Pause)
0128         result |= ADVERTISE_PAUSE_CAP;
0129     if (ethadv & ADVERTISED_Asym_Pause)
0130         result |= ADVERTISE_PAUSE_ASYM;
0131 
0132     return result;
0133 }
0134 
0135 /**
0136  * linkmode_adv_to_mii_adv_t
0137  * @advertising: the linkmode advertisement settings
0138  *
0139  * A small helper function that translates linkmode advertisement
0140  * settings to phy autonegotiation advertisements for the
0141  * MII_ADVERTISE register.
0142  */
0143 static inline u32 linkmode_adv_to_mii_adv_t(unsigned long *advertising)
0144 {
0145     u32 result = 0;
0146 
0147     if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, advertising))
0148         result |= ADVERTISE_10HALF;
0149     if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, advertising))
0150         result |= ADVERTISE_10FULL;
0151     if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, advertising))
0152         result |= ADVERTISE_100HALF;
0153     if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, advertising))
0154         result |= ADVERTISE_100FULL;
0155     if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising))
0156         result |= ADVERTISE_PAUSE_CAP;
0157     if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising))
0158         result |= ADVERTISE_PAUSE_ASYM;
0159 
0160     return result;
0161 }
0162 
0163 /**
0164  * mii_adv_to_ethtool_adv_t
0165  * @adv: value of the MII_ADVERTISE register
0166  *
0167  * A small helper function that translates MII_ADVERTISE bits
0168  * to ethtool advertisement settings.
0169  */
0170 static inline u32 mii_adv_to_ethtool_adv_t(u32 adv)
0171 {
0172     u32 result = 0;
0173 
0174     if (adv & ADVERTISE_10HALF)
0175         result |= ADVERTISED_10baseT_Half;
0176     if (adv & ADVERTISE_10FULL)
0177         result |= ADVERTISED_10baseT_Full;
0178     if (adv & ADVERTISE_100HALF)
0179         result |= ADVERTISED_100baseT_Half;
0180     if (adv & ADVERTISE_100FULL)
0181         result |= ADVERTISED_100baseT_Full;
0182     if (adv & ADVERTISE_PAUSE_CAP)
0183         result |= ADVERTISED_Pause;
0184     if (adv & ADVERTISE_PAUSE_ASYM)
0185         result |= ADVERTISED_Asym_Pause;
0186 
0187     return result;
0188 }
0189 
0190 /**
0191  * ethtool_adv_to_mii_ctrl1000_t
0192  * @ethadv: the ethtool advertisement settings
0193  *
0194  * A small helper function that translates ethtool advertisement
0195  * settings to phy autonegotiation advertisements for the
0196  * MII_CTRL1000 register when in 1000T mode.
0197  */
0198 static inline u32 ethtool_adv_to_mii_ctrl1000_t(u32 ethadv)
0199 {
0200     u32 result = 0;
0201 
0202     if (ethadv & ADVERTISED_1000baseT_Half)
0203         result |= ADVERTISE_1000HALF;
0204     if (ethadv & ADVERTISED_1000baseT_Full)
0205         result |= ADVERTISE_1000FULL;
0206 
0207     return result;
0208 }
0209 
0210 /**
0211  * linkmode_adv_to_mii_ctrl1000_t
0212  * @advertising: the linkmode advertisement settings
0213  *
0214  * A small helper function that translates linkmode advertisement
0215  * settings to phy autonegotiation advertisements for the
0216  * MII_CTRL1000 register when in 1000T mode.
0217  */
0218 static inline u32 linkmode_adv_to_mii_ctrl1000_t(unsigned long *advertising)
0219 {
0220     u32 result = 0;
0221 
0222     if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
0223                   advertising))
0224         result |= ADVERTISE_1000HALF;
0225     if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
0226                   advertising))
0227         result |= ADVERTISE_1000FULL;
0228 
0229     return result;
0230 }
0231 
0232 /**
0233  * mii_ctrl1000_to_ethtool_adv_t
0234  * @adv: value of the MII_CTRL1000 register
0235  *
0236  * A small helper function that translates MII_CTRL1000
0237  * bits, when in 1000Base-T mode, to ethtool
0238  * advertisement settings.
0239  */
0240 static inline u32 mii_ctrl1000_to_ethtool_adv_t(u32 adv)
0241 {
0242     u32 result = 0;
0243 
0244     if (adv & ADVERTISE_1000HALF)
0245         result |= ADVERTISED_1000baseT_Half;
0246     if (adv & ADVERTISE_1000FULL)
0247         result |= ADVERTISED_1000baseT_Full;
0248 
0249     return result;
0250 }
0251 
0252 /**
0253  * mii_lpa_to_ethtool_lpa_t
0254  * @adv: value of the MII_LPA register
0255  *
0256  * A small helper function that translates MII_LPA
0257  * bits, when in 1000Base-T mode, to ethtool
0258  * LP advertisement settings.
0259  */
0260 static inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa)
0261 {
0262     u32 result = 0;
0263 
0264     if (lpa & LPA_LPACK)
0265         result |= ADVERTISED_Autoneg;
0266 
0267     return result | mii_adv_to_ethtool_adv_t(lpa);
0268 }
0269 
0270 /**
0271  * mii_stat1000_to_ethtool_lpa_t
0272  * @adv: value of the MII_STAT1000 register
0273  *
0274  * A small helper function that translates MII_STAT1000
0275  * bits, when in 1000Base-T mode, to ethtool
0276  * advertisement settings.
0277  */
0278 static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa)
0279 {
0280     u32 result = 0;
0281 
0282     if (lpa & LPA_1000HALF)
0283         result |= ADVERTISED_1000baseT_Half;
0284     if (lpa & LPA_1000FULL)
0285         result |= ADVERTISED_1000baseT_Full;
0286 
0287     return result;
0288 }
0289 
0290 /**
0291  * mii_stat1000_mod_linkmode_lpa_t
0292  * @advertising: target the linkmode advertisement settings
0293  * @adv: value of the MII_STAT1000 register
0294  *
0295  * A small helper function that translates MII_STAT1000 bits, when in
0296  * 1000Base-T mode, to linkmode advertisement settings. Other bits in
0297  * advertising are not changes.
0298  */
0299 static inline void mii_stat1000_mod_linkmode_lpa_t(unsigned long *advertising,
0300                            u32 lpa)
0301 {
0302     linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
0303              advertising, lpa & LPA_1000HALF);
0304 
0305     linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
0306              advertising, lpa & LPA_1000FULL);
0307 }
0308 
0309 /**
0310  * ethtool_adv_to_mii_adv_x
0311  * @ethadv: the ethtool advertisement settings
0312  *
0313  * A small helper function that translates ethtool advertisement
0314  * settings to phy autonegotiation advertisements for the
0315  * MII_CTRL1000 register when in 1000Base-X mode.
0316  */
0317 static inline u32 ethtool_adv_to_mii_adv_x(u32 ethadv)
0318 {
0319     u32 result = 0;
0320 
0321     if (ethadv & ADVERTISED_1000baseT_Half)
0322         result |= ADVERTISE_1000XHALF;
0323     if (ethadv & ADVERTISED_1000baseT_Full)
0324         result |= ADVERTISE_1000XFULL;
0325     if (ethadv & ADVERTISED_Pause)
0326         result |= ADVERTISE_1000XPAUSE;
0327     if (ethadv & ADVERTISED_Asym_Pause)
0328         result |= ADVERTISE_1000XPSE_ASYM;
0329 
0330     return result;
0331 }
0332 
0333 /**
0334  * mii_adv_to_ethtool_adv_x
0335  * @adv: value of the MII_CTRL1000 register
0336  *
0337  * A small helper function that translates MII_CTRL1000
0338  * bits, when in 1000Base-X mode, to ethtool
0339  * advertisement settings.
0340  */
0341 static inline u32 mii_adv_to_ethtool_adv_x(u32 adv)
0342 {
0343     u32 result = 0;
0344 
0345     if (adv & ADVERTISE_1000XHALF)
0346         result |= ADVERTISED_1000baseT_Half;
0347     if (adv & ADVERTISE_1000XFULL)
0348         result |= ADVERTISED_1000baseT_Full;
0349     if (adv & ADVERTISE_1000XPAUSE)
0350         result |= ADVERTISED_Pause;
0351     if (adv & ADVERTISE_1000XPSE_ASYM)
0352         result |= ADVERTISED_Asym_Pause;
0353 
0354     return result;
0355 }
0356 
0357 /**
0358  * mii_adv_mod_linkmode_adv_t
0359  * @advertising:pointer to destination link mode.
0360  * @adv: value of the MII_ADVERTISE register
0361  *
0362  * A small helper function that translates MII_ADVERTISE bits to
0363  * linkmode advertisement settings. Leaves other bits unchanged.
0364  */
0365 static inline void mii_adv_mod_linkmode_adv_t(unsigned long *advertising,
0366                           u32 adv)
0367 {
0368     linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
0369              advertising, adv & ADVERTISE_10HALF);
0370 
0371     linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
0372              advertising, adv & ADVERTISE_10FULL);
0373 
0374     linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
0375              advertising, adv & ADVERTISE_100HALF);
0376 
0377     linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
0378              advertising, adv & ADVERTISE_100FULL);
0379 
0380     linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising,
0381              adv & ADVERTISE_PAUSE_CAP);
0382 
0383     linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
0384              advertising, adv & ADVERTISE_PAUSE_ASYM);
0385 }
0386 
0387 /**
0388  * mii_adv_to_linkmode_adv_t
0389  * @advertising:pointer to destination link mode.
0390  * @adv: value of the MII_ADVERTISE register
0391  *
0392  * A small helper function that translates MII_ADVERTISE bits
0393  * to linkmode advertisement settings. Clears the old value
0394  * of advertising.
0395  */
0396 static inline void mii_adv_to_linkmode_adv_t(unsigned long *advertising,
0397                          u32 adv)
0398 {
0399     linkmode_zero(advertising);
0400 
0401     mii_adv_mod_linkmode_adv_t(advertising, adv);
0402 }
0403 
0404 /**
0405  * mii_lpa_to_linkmode_lpa_t
0406  * @adv: value of the MII_LPA register
0407  *
0408  * A small helper function that translates MII_LPA bits, when in
0409  * 1000Base-T mode, to linkmode LP advertisement settings. Clears the
0410  * old value of advertising
0411  */
0412 static inline void mii_lpa_to_linkmode_lpa_t(unsigned long *lp_advertising,
0413                          u32 lpa)
0414 {
0415     mii_adv_to_linkmode_adv_t(lp_advertising, lpa);
0416 
0417     if (lpa & LPA_LPACK)
0418         linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
0419                  lp_advertising);
0420 
0421 }
0422 
0423 /**
0424  * mii_lpa_mod_linkmode_lpa_t
0425  * @adv: value of the MII_LPA register
0426  *
0427  * A small helper function that translates MII_LPA bits, when in
0428  * 1000Base-T mode, to linkmode LP advertisement settings. Leaves
0429  * other bits unchanged.
0430  */
0431 static inline void mii_lpa_mod_linkmode_lpa_t(unsigned long *lp_advertising,
0432                           u32 lpa)
0433 {
0434     mii_adv_mod_linkmode_adv_t(lp_advertising, lpa);
0435 
0436     linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
0437              lp_advertising, lpa & LPA_LPACK);
0438 }
0439 
0440 static inline void mii_ctrl1000_mod_linkmode_adv_t(unsigned long *advertising,
0441                            u32 ctrl1000)
0442 {
0443     linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertising,
0444              ctrl1000 & ADVERTISE_1000HALF);
0445     linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertising,
0446              ctrl1000 & ADVERTISE_1000FULL);
0447 }
0448 
0449 /**
0450  * linkmode_adv_to_lcl_adv_t
0451  * @advertising:pointer to linkmode advertising
0452  *
0453  * A small helper function that translates linkmode advertising to LVL
0454  * pause capabilities.
0455  */
0456 static inline u32 linkmode_adv_to_lcl_adv_t(unsigned long *advertising)
0457 {
0458     u32 lcl_adv = 0;
0459 
0460     if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
0461                   advertising))
0462         lcl_adv |= ADVERTISE_PAUSE_CAP;
0463     if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
0464                   advertising))
0465         lcl_adv |= ADVERTISE_PAUSE_ASYM;
0466 
0467     return lcl_adv;
0468 }
0469 
0470 /**
0471  * mii_lpa_mod_linkmode_x - decode the link partner's config_reg to linkmodes
0472  * @linkmodes: link modes array
0473  * @lpa: config_reg word from link partner
0474  * @fd_bit: link mode for 1000XFULL bit
0475  */
0476 static inline void mii_lpa_mod_linkmode_x(unsigned long *linkmodes, u16 lpa,
0477                      int fd_bit)
0478 {
0479     linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, linkmodes,
0480              lpa & LPA_LPACK);
0481     linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes,
0482              lpa & LPA_1000XPAUSE);
0483     linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes,
0484              lpa & LPA_1000XPAUSE_ASYM);
0485     linkmode_mod_bit(fd_bit, linkmodes,
0486              lpa & LPA_1000XFULL);
0487 }
0488 
0489 /**
0490  * linkmode_adv_to_mii_adv_x - encode a linkmode to config_reg
0491  * @linkmodes: linkmodes
0492  * @fd_bit: full duplex bit
0493  */
0494 static inline u16 linkmode_adv_to_mii_adv_x(const unsigned long *linkmodes,
0495                         int fd_bit)
0496 {
0497     u16 adv = 0;
0498 
0499     if (linkmode_test_bit(fd_bit, linkmodes))
0500         adv |= ADVERTISE_1000XFULL;
0501     if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes))
0502         adv |= ADVERTISE_1000XPAUSE;
0503     if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes))
0504         adv |= ADVERTISE_1000XPSE_ASYM;
0505 
0506     return adv;
0507 }
0508 
0509 /**
0510  * mii_advertise_flowctrl - get flow control advertisement flags
0511  * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)
0512  */
0513 static inline u16 mii_advertise_flowctrl(int cap)
0514 {
0515     u16 adv = 0;
0516 
0517     if (cap & FLOW_CTRL_RX)
0518         adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
0519     if (cap & FLOW_CTRL_TX)
0520         adv ^= ADVERTISE_PAUSE_ASYM;
0521 
0522     return adv;
0523 }
0524 
0525 /**
0526  * mii_resolve_flowctrl_fdx
0527  * @lcladv: value of MII ADVERTISE register
0528  * @rmtadv: value of MII LPA register
0529  *
0530  * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
0531  */
0532 static inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
0533 {
0534     u8 cap = 0;
0535 
0536     if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
0537         cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
0538     } else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
0539         if (lcladv & ADVERTISE_PAUSE_CAP)
0540             cap = FLOW_CTRL_RX;
0541         else if (rmtadv & ADVERTISE_PAUSE_CAP)
0542             cap = FLOW_CTRL_TX;
0543     }
0544 
0545     return cap;
0546 }
0547 
0548 /**
0549  * mii_bmcr_encode_fixed - encode fixed speed/duplex settings to a BMCR value
0550  * @speed: a SPEED_* value
0551  * @duplex: a DUPLEX_* value
0552  *
0553  * Encode the speed and duplex to a BMCR value. 2500, 1000, 100 and 10 Mbps are
0554  * supported. 2500Mbps is encoded to 1000Mbps. Other speeds are encoded as 10
0555  * Mbps. Unknown duplex values are encoded to half-duplex.
0556  */
0557 static inline u16 mii_bmcr_encode_fixed(int speed, int duplex)
0558 {
0559     u16 bmcr;
0560 
0561     switch (speed) {
0562     case SPEED_2500:
0563     case SPEED_1000:
0564         bmcr = BMCR_SPEED1000;
0565         break;
0566 
0567     case SPEED_100:
0568         bmcr = BMCR_SPEED100;
0569         break;
0570 
0571     case SPEED_10:
0572     default:
0573         bmcr = BMCR_SPEED10;
0574         break;
0575     }
0576 
0577     if (duplex == DUPLEX_FULL)
0578         bmcr |= BMCR_FULLDPLX;
0579 
0580     return bmcr;
0581 }
0582 
0583 #endif /* __LINUX_MII_H__ */