Skip to content

Commit ecdad2a

Browse files
Edwin Peerdavem330
authored andcommitted
bnxt_en: add infrastructure to lookup ethtool link mode
Add infrastructure to look up the enum ethtool_link_mode_bit_indices from link information provided by the firmware. The link speed, signal mode, and media type returned by firmware will be used to look up the ethtool link mode. The immediate benefit is that once the link mode is determined, we can now use ethtool_params_from_link_mode() to fill the basic ethtool parameters including the number of lanes. Lanes will be fully supported in the next patch. Signed-off-by: Edwin Peer <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fd78ec3 commit ecdad2a

File tree

2 files changed

+258
-20
lines changed

2 files changed

+258
-20
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,7 @@ struct bnxt_link_info {
12951295
u8 req_signal_mode;
12961296
#define BNXT_SIG_MODE_NRZ PORT_PHY_QCFG_RESP_SIGNAL_MODE_NRZ
12971297
#define BNXT_SIG_MODE_PAM4 PORT_PHY_QCFG_RESP_SIGNAL_MODE_PAM4
1298+
#define BNXT_SIG_MODE_MAX (PORT_PHY_QCFG_RESP_SIGNAL_MODE_LAST + 1)
12981299
u8 req_duplex;
12991300
u8 req_flow_ctrl;
13001301
u16 req_link_speed;

drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

Lines changed: 257 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,230 @@ u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
15061506
return speed_mask;
15071507
}
15081508

1509+
enum bnxt_media_type {
1510+
BNXT_MEDIA_UNKNOWN = 0,
1511+
BNXT_MEDIA_TP,
1512+
BNXT_MEDIA_CR,
1513+
BNXT_MEDIA_SR,
1514+
BNXT_MEDIA_LR_ER_FR,
1515+
BNXT_MEDIA_KR,
1516+
BNXT_MEDIA_KX,
1517+
BNXT_MEDIA_X,
1518+
__BNXT_MEDIA_END,
1519+
};
1520+
1521+
static const enum bnxt_media_type bnxt_phy_types[] = {
1522+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASECR] = BNXT_MEDIA_CR,
1523+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR4] = BNXT_MEDIA_KR,
1524+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASELR] = BNXT_MEDIA_LR_ER_FR,
1525+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASESR] = BNXT_MEDIA_SR,
1526+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR2] = BNXT_MEDIA_KR,
1527+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKX] = BNXT_MEDIA_KX,
1528+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASEKR] = BNXT_MEDIA_KR,
1529+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASET] = BNXT_MEDIA_TP,
1530+
[PORT_PHY_QCFG_RESP_PHY_TYPE_BASETE] = BNXT_MEDIA_TP,
1531+
[PORT_PHY_QCFG_RESP_PHY_TYPE_25G_BASECR_CA_L] = BNXT_MEDIA_CR,
1532+
[PORT_PHY_QCFG_RESP_PHY_TYPE_25G_BASECR_CA_S] = BNXT_MEDIA_CR,
1533+
[PORT_PHY_QCFG_RESP_PHY_TYPE_25G_BASECR_CA_N] = BNXT_MEDIA_CR,
1534+
[PORT_PHY_QCFG_RESP_PHY_TYPE_25G_BASESR] = BNXT_MEDIA_SR,
1535+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR4] = BNXT_MEDIA_CR,
1536+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR4] = BNXT_MEDIA_SR,
1537+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR4] = BNXT_MEDIA_LR_ER_FR,
1538+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER4] = BNXT_MEDIA_LR_ER_FR,
1539+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR10] = BNXT_MEDIA_SR,
1540+
[PORT_PHY_QCFG_RESP_PHY_TYPE_40G_BASECR4] = BNXT_MEDIA_CR,
1541+
[PORT_PHY_QCFG_RESP_PHY_TYPE_40G_BASESR4] = BNXT_MEDIA_SR,
1542+
[PORT_PHY_QCFG_RESP_PHY_TYPE_40G_BASELR4] = BNXT_MEDIA_LR_ER_FR,
1543+
[PORT_PHY_QCFG_RESP_PHY_TYPE_40G_BASEER4] = BNXT_MEDIA_LR_ER_FR,
1544+
[PORT_PHY_QCFG_RESP_PHY_TYPE_40G_ACTIVE_CABLE] = BNXT_MEDIA_SR,
1545+
[PORT_PHY_QCFG_RESP_PHY_TYPE_1G_BASET] = BNXT_MEDIA_TP,
1546+
[PORT_PHY_QCFG_RESP_PHY_TYPE_1G_BASESX] = BNXT_MEDIA_X,
1547+
[PORT_PHY_QCFG_RESP_PHY_TYPE_1G_BASECX] = BNXT_MEDIA_X,
1548+
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASECR4] = BNXT_MEDIA_CR,
1549+
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASESR4] = BNXT_MEDIA_SR,
1550+
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASELR4] = BNXT_MEDIA_LR_ER_FR,
1551+
[PORT_PHY_QCFG_RESP_PHY_TYPE_200G_BASEER4] = BNXT_MEDIA_LR_ER_FR,
1552+
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASECR] = BNXT_MEDIA_CR,
1553+
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASESR] = BNXT_MEDIA_SR,
1554+
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASELR] = BNXT_MEDIA_LR_ER_FR,
1555+
[PORT_PHY_QCFG_RESP_PHY_TYPE_50G_BASEER] = BNXT_MEDIA_LR_ER_FR,
1556+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASECR2] = BNXT_MEDIA_CR,
1557+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASESR2] = BNXT_MEDIA_SR,
1558+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASELR2] = BNXT_MEDIA_LR_ER_FR,
1559+
[PORT_PHY_QCFG_RESP_PHY_TYPE_100G_BASEER2] = BNXT_MEDIA_LR_ER_FR,
1560+
};
1561+
1562+
static enum bnxt_media_type
1563+
bnxt_get_media(struct bnxt_link_info *link_info)
1564+
{
1565+
switch (link_info->media_type) {
1566+
case PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP:
1567+
return BNXT_MEDIA_TP;
1568+
case PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC:
1569+
return BNXT_MEDIA_CR;
1570+
default:
1571+
if (link_info->phy_type < ARRAY_SIZE(bnxt_phy_types))
1572+
return bnxt_phy_types[link_info->phy_type];
1573+
return BNXT_MEDIA_UNKNOWN;
1574+
}
1575+
}
1576+
1577+
enum bnxt_link_speed_indices {
1578+
BNXT_LINK_SPEED_UNKNOWN = 0,
1579+
BNXT_LINK_SPEED_100MB_IDX,
1580+
BNXT_LINK_SPEED_1GB_IDX,
1581+
BNXT_LINK_SPEED_10GB_IDX,
1582+
BNXT_LINK_SPEED_25GB_IDX,
1583+
BNXT_LINK_SPEED_40GB_IDX,
1584+
BNXT_LINK_SPEED_50GB_IDX,
1585+
BNXT_LINK_SPEED_100GB_IDX,
1586+
BNXT_LINK_SPEED_200GB_IDX,
1587+
__BNXT_LINK_SPEED_END
1588+
};
1589+
1590+
static enum bnxt_link_speed_indices bnxt_fw_speed_idx(u16 speed)
1591+
{
1592+
switch (speed) {
1593+
case BNXT_LINK_SPEED_100MB: return BNXT_LINK_SPEED_100MB_IDX;
1594+
case BNXT_LINK_SPEED_1GB: return BNXT_LINK_SPEED_1GB_IDX;
1595+
case BNXT_LINK_SPEED_10GB: return BNXT_LINK_SPEED_10GB_IDX;
1596+
case BNXT_LINK_SPEED_25GB: return BNXT_LINK_SPEED_25GB_IDX;
1597+
case BNXT_LINK_SPEED_40GB: return BNXT_LINK_SPEED_40GB_IDX;
1598+
case BNXT_LINK_SPEED_50GB: return BNXT_LINK_SPEED_50GB_IDX;
1599+
case BNXT_LINK_SPEED_100GB: return BNXT_LINK_SPEED_100GB_IDX;
1600+
case BNXT_LINK_SPEED_200GB: return BNXT_LINK_SPEED_200GB_IDX;
1601+
default: return BNXT_LINK_SPEED_UNKNOWN;
1602+
}
1603+
}
1604+
1605+
static const enum ethtool_link_mode_bit_indices
1606+
bnxt_link_modes[__BNXT_LINK_SPEED_END][BNXT_SIG_MODE_MAX][__BNXT_MEDIA_END] = {
1607+
[BNXT_LINK_SPEED_100MB_IDX] = {
1608+
{
1609+
[BNXT_MEDIA_TP] = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
1610+
},
1611+
},
1612+
[BNXT_LINK_SPEED_1GB_IDX] = {
1613+
{
1614+
[BNXT_MEDIA_TP] = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
1615+
/* historically baseT, but DAC is more correctly baseX */
1616+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
1617+
[BNXT_MEDIA_KX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
1618+
[BNXT_MEDIA_X] = ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
1619+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
1620+
},
1621+
},
1622+
[BNXT_LINK_SPEED_10GB_IDX] = {
1623+
{
1624+
[BNXT_MEDIA_TP] = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
1625+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
1626+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
1627+
[BNXT_MEDIA_LR_ER_FR] = ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
1628+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
1629+
[BNXT_MEDIA_KX] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
1630+
},
1631+
},
1632+
[BNXT_LINK_SPEED_25GB_IDX] = {
1633+
{
1634+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
1635+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
1636+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
1637+
},
1638+
},
1639+
[BNXT_LINK_SPEED_40GB_IDX] = {
1640+
{
1641+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
1642+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
1643+
[BNXT_MEDIA_LR_ER_FR] = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
1644+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
1645+
},
1646+
},
1647+
[BNXT_LINK_SPEED_50GB_IDX] = {
1648+
[BNXT_SIG_MODE_NRZ] = {
1649+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
1650+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
1651+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
1652+
},
1653+
[BNXT_SIG_MODE_PAM4] = {
1654+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
1655+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
1656+
[BNXT_MEDIA_LR_ER_FR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
1657+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
1658+
},
1659+
},
1660+
[BNXT_LINK_SPEED_100GB_IDX] = {
1661+
[BNXT_SIG_MODE_NRZ] = {
1662+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
1663+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
1664+
[BNXT_MEDIA_LR_ER_FR] = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
1665+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
1666+
},
1667+
[BNXT_SIG_MODE_PAM4] = {
1668+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
1669+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
1670+
[BNXT_MEDIA_LR_ER_FR] = ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
1671+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
1672+
},
1673+
},
1674+
[BNXT_LINK_SPEED_200GB_IDX] = {
1675+
[BNXT_SIG_MODE_PAM4] = {
1676+
[BNXT_MEDIA_CR] = ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
1677+
[BNXT_MEDIA_SR] = ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
1678+
[BNXT_MEDIA_LR_ER_FR] = ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
1679+
[BNXT_MEDIA_KR] = ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
1680+
},
1681+
},
1682+
};
1683+
1684+
#define BNXT_LINK_MODE_UNKNOWN -1
1685+
1686+
static enum ethtool_link_mode_bit_indices
1687+
bnxt_get_link_mode(struct bnxt_link_info *link_info)
1688+
{
1689+
enum ethtool_link_mode_bit_indices link_mode;
1690+
enum bnxt_link_speed_indices speed;
1691+
enum bnxt_media_type media;
1692+
u8 sig_mode;
1693+
1694+
if (link_info->phy_link_status != BNXT_LINK_LINK)
1695+
return BNXT_LINK_MODE_UNKNOWN;
1696+
1697+
media = bnxt_get_media(link_info);
1698+
if (BNXT_AUTO_MODE(link_info->auto_mode)) {
1699+
speed = bnxt_fw_speed_idx(link_info->link_speed);
1700+
sig_mode = link_info->active_fec_sig_mode &
1701+
PORT_PHY_QCFG_RESP_SIGNAL_MODE_MASK;
1702+
} else {
1703+
speed = bnxt_fw_speed_idx(link_info->req_link_speed);
1704+
sig_mode = link_info->req_signal_mode;
1705+
}
1706+
if (sig_mode >= BNXT_SIG_MODE_MAX)
1707+
return BNXT_LINK_MODE_UNKNOWN;
1708+
1709+
/* Note ETHTOOL_LINK_MODE_10baseT_Half_BIT == 0 is a legal Linux
1710+
* link mode, but since no such devices exist, the zeroes in the
1711+
* map can be conveniently used to represent unknown link modes.
1712+
*/
1713+
link_mode = bnxt_link_modes[speed][sig_mode][media];
1714+
if (!link_mode)
1715+
return BNXT_LINK_MODE_UNKNOWN;
1716+
1717+
switch (link_mode) {
1718+
case ETHTOOL_LINK_MODE_100baseT_Full_BIT:
1719+
if (~link_info->duplex & BNXT_LINK_DUPLEX_FULL)
1720+
link_mode = ETHTOOL_LINK_MODE_100baseT_Half_BIT;
1721+
break;
1722+
case ETHTOOL_LINK_MODE_1000baseT_Full_BIT:
1723+
if (~link_info->duplex & BNXT_LINK_DUPLEX_FULL)
1724+
link_mode = ETHTOOL_LINK_MODE_1000baseT_Half_BIT;
1725+
break;
1726+
default:
1727+
break;
1728+
}
1729+
1730+
return link_mode;
1731+
}
1732+
15091733
#define BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings, name)\
15101734
{ \
15111735
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_100MB) \
@@ -1720,42 +1944,56 @@ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
17201944
}
17211945
}
17221946

1947+
static void bnxt_get_default_speeds(struct ethtool_link_ksettings *lk_ksettings,
1948+
struct bnxt_link_info *link_info)
1949+
{
1950+
struct ethtool_link_settings *base = &lk_ksettings->base;
1951+
1952+
if (link_info->link_state == BNXT_LINK_STATE_UP) {
1953+
base->speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
1954+
base->duplex = DUPLEX_HALF;
1955+
if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
1956+
base->duplex = DUPLEX_FULL;
1957+
} else if (!link_info->autoneg) {
1958+
base->speed = bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
1959+
base->duplex = DUPLEX_HALF;
1960+
if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL)
1961+
base->duplex = DUPLEX_FULL;
1962+
}
1963+
}
1964+
17231965
static int bnxt_get_link_ksettings(struct net_device *dev,
17241966
struct ethtool_link_ksettings *lk_ksettings)
17251967
{
1726-
struct bnxt *bp = netdev_priv(dev);
1727-
struct bnxt_link_info *link_info = &bp->link_info;
17281968
struct ethtool_link_settings *base = &lk_ksettings->base;
1729-
u32 ethtool_speed;
1969+
enum ethtool_link_mode_bit_indices link_mode;
1970+
struct bnxt *bp = netdev_priv(dev);
1971+
struct bnxt_link_info *link_info;
17301972

1973+
ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising);
17311974
ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported);
1975+
base->duplex = DUPLEX_UNKNOWN;
1976+
base->speed = SPEED_UNKNOWN;
1977+
link_info = &bp->link_info;
1978+
17321979
mutex_lock(&bp->link_lock);
17331980
bnxt_fw_to_ethtool_support_spds(link_info, lk_ksettings);
1981+
link_mode = bnxt_get_link_mode(link_info);
1982+
if (link_mode != BNXT_LINK_MODE_UNKNOWN)
1983+
ethtool_params_from_link_mode(lk_ksettings, link_mode);
1984+
else
1985+
bnxt_get_default_speeds(lk_ksettings, link_info);
17341986

1735-
ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising);
17361987
if (link_info->autoneg) {
17371988
bnxt_fw_to_ethtool_advertised_spds(link_info, lk_ksettings);
17381989
ethtool_link_ksettings_add_link_mode(lk_ksettings,
17391990
advertising, Autoneg);
17401991
base->autoneg = AUTONEG_ENABLE;
1741-
base->duplex = DUPLEX_UNKNOWN;
1742-
if (link_info->phy_link_status == BNXT_LINK_LINK) {
1992+
if (link_info->phy_link_status == BNXT_LINK_LINK)
17431993
bnxt_fw_to_ethtool_lp_adv(link_info, lk_ksettings);
1744-
if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
1745-
base->duplex = DUPLEX_FULL;
1746-
else
1747-
base->duplex = DUPLEX_HALF;
1748-
}
1749-
ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
17501994
} else {
17511995
base->autoneg = AUTONEG_DISABLE;
1752-
ethtool_speed =
1753-
bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
1754-
base->duplex = DUPLEX_HALF;
1755-
if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL)
1756-
base->duplex = DUPLEX_FULL;
17571996
}
1758-
base->speed = ethtool_speed;
17591997

17601998
base->port = PORT_NONE;
17611999
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
@@ -1772,8 +2010,7 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
17722010

17732011
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
17742012
base->port = PORT_DA;
1775-
else if (link_info->media_type ==
1776-
PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE)
2013+
else
17772014
base->port = PORT_FIBRE;
17782015
}
17792016
base->phy_address = link_info->phy_addr;

0 commit comments

Comments
 (0)