Skip to content

Commit 5d4e1bf

Browse files
Edwin Peerdavem330
authored andcommitted
bnxt_en: extend media types to supported and autoneg modes
The current driver code does not accurately report the supported and advertised link modes. It basically always assumes the media type is copper for any particular speed. Utilize the recently added link mode mappings to accurately report fully qualified ethtool link modes for advertised and supported speeds. If the media type is known, we will report the supported link modes for that media only. If the media is not known, we will report all possible supported link modes. The user can now specify any supported link modes (including NRZ and PAM4) to advertise for autoneg. It used to only accept copper NRZ modes. Signed-off-by: Edwin Peer <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 64d20ae commit 5d4e1bf

File tree

1 file changed

+153
-120
lines changed

1 file changed

+153
-120
lines changed

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

Lines changed: 153 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* the Free Software Foundation.
99
*/
1010

11+
#include <linux/bitops.h>
1112
#include <linux/ctype.h>
1213
#include <linux/stringify.h>
1314
#include <linux/ethtool.h>
@@ -1730,86 +1731,6 @@ bnxt_get_link_mode(struct bnxt_link_info *link_info)
17301731
return link_mode;
17311732
}
17321733

1733-
#define BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, lk_ksettings, name) \
1734-
{ \
1735-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_100MB) \
1736-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1737-
100baseT_Full); \
1738-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_1GB) \
1739-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1740-
1000baseT_Full); \
1741-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_10GB) \
1742-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1743-
10000baseT_Full); \
1744-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_25GB) \
1745-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1746-
25000baseCR_Full); \
1747-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_40GB) \
1748-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1749-
40000baseCR4_Full);\
1750-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_50GB) \
1751-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1752-
50000baseCR2_Full);\
1753-
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_100GB) \
1754-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1755-
100000baseCR4_Full);\
1756-
}
1757-
1758-
#define BNXT_ETHTOOL_TO_FW_SPDS(fw_speeds, lk_ksettings, name) \
1759-
{ \
1760-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1761-
100baseT_Full) || \
1762-
ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1763-
100baseT_Half)) \
1764-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_100MB; \
1765-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1766-
1000baseT_Full) || \
1767-
ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1768-
1000baseT_Half)) \
1769-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_1GB; \
1770-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1771-
10000baseT_Full)) \
1772-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_10GB; \
1773-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1774-
25000baseCR_Full)) \
1775-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_25GB; \
1776-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1777-
40000baseCR4_Full)) \
1778-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_40GB; \
1779-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1780-
50000baseCR2_Full)) \
1781-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_50GB; \
1782-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1783-
100000baseCR4_Full)) \
1784-
(fw_speeds) |= BNXT_LINK_SPEED_MSK_100GB; \
1785-
}
1786-
1787-
#define BNXT_FW_TO_ETHTOOL_PAM4_SPDS(fw_speeds, lk_ksettings, name) \
1788-
{ \
1789-
if ((fw_speeds) & BNXT_LINK_PAM4_SPEED_MSK_50GB) \
1790-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1791-
50000baseCR_Full); \
1792-
if ((fw_speeds) & BNXT_LINK_PAM4_SPEED_MSK_100GB) \
1793-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1794-
100000baseCR2_Full);\
1795-
if ((fw_speeds) & BNXT_LINK_PAM4_SPEED_MSK_200GB) \
1796-
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
1797-
200000baseCR4_Full);\
1798-
}
1799-
1800-
#define BNXT_ETHTOOL_TO_FW_PAM4_SPDS(fw_speeds, lk_ksettings, name) \
1801-
{ \
1802-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1803-
50000baseCR_Full)) \
1804-
(fw_speeds) |= BNXT_LINK_PAM4_SPEED_MSK_50GB; \
1805-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1806-
100000baseCR2_Full)) \
1807-
(fw_speeds) |= BNXT_LINK_PAM4_SPEED_MSK_100GB; \
1808-
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
1809-
200000baseCR4_Full)) \
1810-
(fw_speeds) |= BNXT_LINK_PAM4_SPEED_MSK_200GB; \
1811-
}
1812-
18131734
static void bnxt_get_ethtool_modes(struct bnxt_link_info *link_info,
18141735
struct ethtool_link_ksettings *lk_ksettings)
18151736
{
@@ -1843,6 +1764,133 @@ static void bnxt_get_ethtool_modes(struct bnxt_link_info *link_info,
18431764
lk_ksettings->link_modes.lp_advertising);
18441765
}
18451766

1767+
static const u16 bnxt_nrz_speed_masks[] = {
1768+
[BNXT_LINK_SPEED_100MB_IDX] = BNXT_LINK_SPEED_MSK_100MB,
1769+
[BNXT_LINK_SPEED_1GB_IDX] = BNXT_LINK_SPEED_MSK_1GB,
1770+
[BNXT_LINK_SPEED_10GB_IDX] = BNXT_LINK_SPEED_MSK_10GB,
1771+
[BNXT_LINK_SPEED_25GB_IDX] = BNXT_LINK_SPEED_MSK_25GB,
1772+
[BNXT_LINK_SPEED_40GB_IDX] = BNXT_LINK_SPEED_MSK_40GB,
1773+
[BNXT_LINK_SPEED_50GB_IDX] = BNXT_LINK_SPEED_MSK_50GB,
1774+
[BNXT_LINK_SPEED_100GB_IDX] = BNXT_LINK_SPEED_MSK_100GB,
1775+
[__BNXT_LINK_SPEED_END - 1] = 0 /* make any legal speed a valid index */
1776+
};
1777+
1778+
static const u16 bnxt_pam4_speed_masks[] = {
1779+
[BNXT_LINK_SPEED_50GB_IDX] = BNXT_LINK_PAM4_SPEED_MSK_50GB,
1780+
[BNXT_LINK_SPEED_100GB_IDX] = BNXT_LINK_PAM4_SPEED_MSK_100GB,
1781+
[BNXT_LINK_SPEED_200GB_IDX] = BNXT_LINK_PAM4_SPEED_MSK_200GB,
1782+
};
1783+
1784+
static enum bnxt_link_speed_indices
1785+
bnxt_encoding_speed_idx(u8 sig_mode, u16 speed_msk)
1786+
{
1787+
const u16 *speeds;
1788+
int idx, len;
1789+
1790+
switch (sig_mode) {
1791+
case BNXT_SIG_MODE_NRZ:
1792+
speeds = bnxt_nrz_speed_masks;
1793+
len = ARRAY_SIZE(bnxt_nrz_speed_masks);
1794+
break;
1795+
case BNXT_SIG_MODE_PAM4:
1796+
speeds = bnxt_pam4_speed_masks;
1797+
len = ARRAY_SIZE(bnxt_pam4_speed_masks);
1798+
break;
1799+
default:
1800+
return BNXT_LINK_SPEED_UNKNOWN;
1801+
}
1802+
1803+
for (idx = 0; idx < len; idx++) {
1804+
if (speeds[idx] == speed_msk)
1805+
return idx;
1806+
}
1807+
1808+
return BNXT_LINK_SPEED_UNKNOWN;
1809+
}
1810+
1811+
#define BNXT_FW_SPEED_MSK_BITS 16
1812+
1813+
static void
1814+
__bnxt_get_ethtool_speeds(unsigned long fw_mask, enum bnxt_media_type media,
1815+
u8 sig_mode, unsigned long *et_mask)
1816+
{
1817+
enum ethtool_link_mode_bit_indices link_mode;
1818+
enum bnxt_link_speed_indices speed;
1819+
u8 bit;
1820+
1821+
for_each_set_bit(bit, &fw_mask, BNXT_FW_SPEED_MSK_BITS) {
1822+
speed = bnxt_encoding_speed_idx(sig_mode, 1 << bit);
1823+
if (!speed)
1824+
continue;
1825+
1826+
link_mode = bnxt_link_modes[speed][sig_mode][media];
1827+
if (!link_mode)
1828+
continue;
1829+
1830+
linkmode_set_bit(link_mode, et_mask);
1831+
}
1832+
}
1833+
1834+
static void
1835+
bnxt_get_ethtool_speeds(unsigned long fw_mask, enum bnxt_media_type media,
1836+
u8 sig_mode, unsigned long *et_mask)
1837+
{
1838+
if (media) {
1839+
__bnxt_get_ethtool_speeds(fw_mask, media, sig_mode, et_mask);
1840+
return;
1841+
}
1842+
1843+
/* list speeds for all media if unknown */
1844+
for (media = 1; media < __BNXT_MEDIA_END; media++)
1845+
__bnxt_get_ethtool_speeds(fw_mask, media, sig_mode, et_mask);
1846+
}
1847+
1848+
static void bnxt_update_speed(u32 *delta, bool installed_media, u16 *speeds,
1849+
u16 speed_msk, const unsigned long *et_mask,
1850+
enum ethtool_link_mode_bit_indices mode)
1851+
{
1852+
bool mode_desired = linkmode_test_bit(mode, et_mask);
1853+
1854+
if (!mode)
1855+
return;
1856+
1857+
/* enabled speeds for installed media should override */
1858+
if (installed_media && mode_desired) {
1859+
*speeds |= speed_msk;
1860+
*delta |= speed_msk;
1861+
return;
1862+
}
1863+
1864+
/* many to one mapping, only allow one change per fw_speed bit */
1865+
if (!(*delta & speed_msk) && (mode_desired == !(*speeds & speed_msk))) {
1866+
*speeds ^= speed_msk;
1867+
*delta |= speed_msk;
1868+
}
1869+
}
1870+
1871+
static void bnxt_set_ethtool_speeds(struct bnxt_link_info *link_info,
1872+
const unsigned long *et_mask)
1873+
{
1874+
enum bnxt_media_type media = bnxt_get_media(link_info);
1875+
u32 delta_pam4 = 0;
1876+
u32 delta_nrz = 0;
1877+
int i, m;
1878+
1879+
for (i = 1; i < __BNXT_LINK_SPEED_END; i++) {
1880+
/* accept any legal media from user */
1881+
for (m = 1; m < __BNXT_MEDIA_END; m++) {
1882+
bnxt_update_speed(&delta_nrz, m == media,
1883+
&link_info->advertising,
1884+
bnxt_nrz_speed_masks[i], et_mask,
1885+
bnxt_link_modes[i][BNXT_SIG_MODE_NRZ][m]);
1886+
bnxt_update_speed(&delta_pam4, m == media,
1887+
&link_info->advertising_pam4,
1888+
bnxt_pam4_speed_masks[i], et_mask,
1889+
bnxt_link_modes[i][BNXT_SIG_MODE_PAM4][m]);
1890+
}
1891+
}
1892+
}
1893+
18461894
static void bnxt_fw_to_ethtool_advertised_fec(struct bnxt_link_info *link_info,
18471895
struct ethtool_link_ksettings *lk_ksettings)
18481896
{
@@ -1864,26 +1912,6 @@ static void bnxt_fw_to_ethtool_advertised_fec(struct bnxt_link_info *link_info,
18641912
lk_ksettings->link_modes.advertising);
18651913
}
18661914

1867-
static void bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info,
1868-
struct ethtool_link_ksettings *lk_ksettings)
1869-
{
1870-
u16 fw_speeds = link_info->advertising;
1871-
1872-
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, lk_ksettings, advertising);
1873-
fw_speeds = link_info->advertising_pam4;
1874-
BNXT_FW_TO_ETHTOOL_PAM4_SPDS(fw_speeds, lk_ksettings, advertising);
1875-
}
1876-
1877-
static void bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info,
1878-
struct ethtool_link_ksettings *lk_ksettings)
1879-
{
1880-
u16 fw_speeds = link_info->lp_auto_link_speeds;
1881-
1882-
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, lk_ksettings, lp_advertising);
1883-
fw_speeds = link_info->lp_auto_pam4_link_speeds;
1884-
BNXT_FW_TO_ETHTOOL_PAM4_SPDS(fw_speeds, lk_ksettings, lp_advertising);
1885-
}
1886-
18871915
static void bnxt_fw_to_ethtool_support_fec(struct bnxt_link_info *link_info,
18881916
struct ethtool_link_ksettings *lk_ksettings)
18891917
{
@@ -1905,16 +1933,6 @@ static void bnxt_fw_to_ethtool_support_fec(struct bnxt_link_info *link_info,
19051933
lk_ksettings->link_modes.supported);
19061934
}
19071935

1908-
static void bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info,
1909-
struct ethtool_link_ksettings *lk_ksettings)
1910-
{
1911-
u16 fw_speeds = link_info->support_speeds;
1912-
1913-
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, lk_ksettings, supported);
1914-
fw_speeds = link_info->support_pam4_speeds;
1915-
BNXT_FW_TO_ETHTOOL_PAM4_SPDS(fw_speeds, lk_ksettings, supported);
1916-
}
1917-
19181936
u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
19191937
{
19201938
switch (fw_link_speed) {
@@ -1968,7 +1986,9 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
19681986
enum ethtool_link_mode_bit_indices link_mode;
19691987
struct bnxt *bp = netdev_priv(dev);
19701988
struct bnxt_link_info *link_info;
1989+
enum bnxt_media_type media;
19711990

1991+
ethtool_link_ksettings_zero_link_mode(lk_ksettings, lp_advertising);
19721992
ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising);
19731993
ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported);
19741994
base->duplex = DUPLEX_UNKNOWN;
@@ -1977,7 +1997,13 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
19771997

19781998
mutex_lock(&bp->link_lock);
19791999
bnxt_get_ethtool_modes(link_info, lk_ksettings);
1980-
bnxt_fw_to_ethtool_support_spds(link_info, lk_ksettings);
2000+
media = bnxt_get_media(link_info);
2001+
bnxt_get_ethtool_speeds(link_info->support_speeds,
2002+
media, BNXT_SIG_MODE_NRZ,
2003+
lk_ksettings->link_modes.supported);
2004+
bnxt_get_ethtool_speeds(link_info->support_pam4_speeds,
2005+
media, BNXT_SIG_MODE_PAM4,
2006+
lk_ksettings->link_modes.supported);
19812007
bnxt_fw_to_ethtool_support_fec(link_info, lk_ksettings);
19822008
link_mode = bnxt_get_link_mode(link_info);
19832009
if (link_mode != BNXT_LINK_MODE_UNKNOWN)
@@ -1986,13 +2012,24 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
19862012
bnxt_get_default_speeds(lk_ksettings, link_info);
19872013

19882014
if (link_info->autoneg) {
1989-
bnxt_fw_to_ethtool_advertised_spds(link_info, lk_ksettings);
19902015
bnxt_fw_to_ethtool_advertised_fec(link_info, lk_ksettings);
19912016
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
19922017
lk_ksettings->link_modes.advertising);
19932018
base->autoneg = AUTONEG_ENABLE;
1994-
if (link_info->phy_link_status == BNXT_LINK_LINK)
1995-
bnxt_fw_to_ethtool_lp_adv(link_info, lk_ksettings);
2019+
bnxt_get_ethtool_speeds(link_info->advertising,
2020+
media, BNXT_SIG_MODE_NRZ,
2021+
lk_ksettings->link_modes.advertising);
2022+
bnxt_get_ethtool_speeds(link_info->advertising_pam4,
2023+
media, BNXT_SIG_MODE_PAM4,
2024+
lk_ksettings->link_modes.advertising);
2025+
if (link_info->phy_link_status == BNXT_LINK_LINK) {
2026+
bnxt_get_ethtool_speeds(link_info->lp_auto_link_speeds,
2027+
media, BNXT_SIG_MODE_NRZ,
2028+
lk_ksettings->link_modes.lp_advertising);
2029+
bnxt_get_ethtool_speeds(link_info->lp_auto_pam4_link_speeds,
2030+
media, BNXT_SIG_MODE_PAM4,
2031+
lk_ksettings->link_modes.lp_advertising);
2032+
}
19962033
} else {
19972034
base->autoneg = AUTONEG_DISABLE;
19982035
}
@@ -2156,12 +2193,8 @@ static int bnxt_set_link_ksettings(struct net_device *dev,
21562193

21572194
mutex_lock(&bp->link_lock);
21582195
if (base->autoneg == AUTONEG_ENABLE) {
2159-
link_info->advertising = 0;
2160-
link_info->advertising_pam4 = 0;
2161-
BNXT_ETHTOOL_TO_FW_SPDS(link_info->advertising, lk_ksettings,
2162-
advertising);
2163-
BNXT_ETHTOOL_TO_FW_PAM4_SPDS(link_info->advertising_pam4,
2164-
lk_ksettings, advertising);
2196+
bnxt_set_ethtool_speeds(link_info,
2197+
lk_ksettings->link_modes.advertising);
21652198
link_info->autoneg |= BNXT_AUTONEG_SPEED;
21662199
if (!link_info->advertising && !link_info->advertising_pam4) {
21672200
link_info->advertising = link_info->support_auto_speeds;

0 commit comments

Comments
 (0)