Skip to content

Commit 00c04a9

Browse files
Michael Chandavem330
authored andcommitted
bnxt_en: Support new ETHTOOL_{G|S}LINKSETTINGS API.
To fully support 25G and 50G link settings. Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 93ed811 commit 00c04a9

File tree

1 file changed

+118
-80
lines changed

1 file changed

+118
-80
lines changed

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

Lines changed: 118 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -628,46 +628,103 @@ u32 _bnxt_fw_to_ethtool_adv_spds(u16 fw_speeds, u8 fw_pause)
628628
return speed_mask;
629629
}
630630

631-
static u32 bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info)
631+
#define BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings, name)\
632+
{ \
633+
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_100MB) \
634+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
635+
100baseT_Full); \
636+
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_1GB) \
637+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
638+
1000baseT_Full); \
639+
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_10GB) \
640+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
641+
10000baseT_Full); \
642+
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_25GB) \
643+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
644+
25000baseCR_Full); \
645+
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_40GB) \
646+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
647+
40000baseCR4_Full);\
648+
if ((fw_speeds) & BNXT_LINK_SPEED_MSK_50GB) \
649+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
650+
50000baseCR2_Full);\
651+
if ((fw_pause) & BNXT_LINK_PAUSE_RX) { \
652+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
653+
Pause); \
654+
if (!((fw_pause) & BNXT_LINK_PAUSE_TX)) \
655+
ethtool_link_ksettings_add_link_mode( \
656+
lk_ksettings, name, Asym_Pause);\
657+
} else if ((fw_pause) & BNXT_LINK_PAUSE_TX) { \
658+
ethtool_link_ksettings_add_link_mode(lk_ksettings, name,\
659+
Asym_Pause); \
660+
} \
661+
}
662+
663+
#define BNXT_ETHTOOL_TO_FW_SPDS(fw_speeds, lk_ksettings, name) \
664+
{ \
665+
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
666+
100baseT_Full) || \
667+
ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
668+
100baseT_Half)) \
669+
(fw_speeds) |= BNXT_LINK_SPEED_MSK_100MB; \
670+
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
671+
1000baseT_Full) || \
672+
ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
673+
1000baseT_Half)) \
674+
(fw_speeds) |= BNXT_LINK_SPEED_MSK_1GB; \
675+
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
676+
10000baseT_Full)) \
677+
(fw_speeds) |= BNXT_LINK_SPEED_MSK_10GB; \
678+
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
679+
25000baseCR_Full)) \
680+
(fw_speeds) |= BNXT_LINK_SPEED_MSK_25GB; \
681+
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
682+
40000baseCR4_Full)) \
683+
(fw_speeds) |= BNXT_LINK_SPEED_MSK_40GB; \
684+
if (ethtool_link_ksettings_test_link_mode(lk_ksettings, name, \
685+
50000baseCR2_Full)) \
686+
(fw_speeds) |= BNXT_LINK_SPEED_MSK_50GB; \
687+
}
688+
689+
static void bnxt_fw_to_ethtool_advertised_spds(struct bnxt_link_info *link_info,
690+
struct ethtool_link_ksettings *lk_ksettings)
632691
{
633692
u16 fw_speeds = link_info->auto_link_speeds;
634693
u8 fw_pause = 0;
635694

636695
if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
637696
fw_pause = link_info->auto_pause_setting;
638697

639-
return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause);
698+
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings, advertising);
640699
}
641700

642-
static u32 bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info)
701+
static void bnxt_fw_to_ethtool_lp_adv(struct bnxt_link_info *link_info,
702+
struct ethtool_link_ksettings *lk_ksettings)
643703
{
644704
u16 fw_speeds = link_info->lp_auto_link_speeds;
645705
u8 fw_pause = 0;
646706

647707
if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
648708
fw_pause = link_info->lp_pause;
649709

650-
return _bnxt_fw_to_ethtool_adv_spds(fw_speeds, fw_pause);
710+
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, fw_pause, lk_ksettings,
711+
lp_advertising);
651712
}
652713

653-
static u32 bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info)
714+
static void bnxt_fw_to_ethtool_support_spds(struct bnxt_link_info *link_info,
715+
struct ethtool_link_ksettings *lk_ksettings)
654716
{
655717
u16 fw_speeds = link_info->support_speeds;
656-
u32 supported;
657718

658-
supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0);
659-
return supported | SUPPORTED_Pause | SUPPORTED_Asym_Pause;
660-
}
719+
BNXT_FW_TO_ETHTOOL_SPDS(fw_speeds, 0, lk_ksettings, supported);
661720

662-
static u32 bnxt_fw_to_ethtool_support_adv_spds(struct bnxt_link_info *link_info)
663-
{
664-
u16 fw_speeds = link_info->support_auto_speeds;
665-
u32 supported;
721+
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported, Pause);
722+
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
723+
Asym_Pause);
666724

667-
supported = _bnxt_fw_to_ethtool_adv_spds(fw_speeds, 0);
668-
if (supported)
669-
supported |= SUPPORTED_Pause | SUPPORTED_Asym_Pause;
670-
return supported;
725+
if (link_info->support_auto_speeds)
726+
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
727+
Autoneg);
671728
}
672729

673730
u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
@@ -694,65 +751,62 @@ u32 bnxt_fw_to_ethtool_speed(u16 fw_link_speed)
694751
}
695752
}
696753

697-
static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
754+
static int bnxt_get_link_ksettings(struct net_device *dev,
755+
struct ethtool_link_ksettings *lk_ksettings)
698756
{
699757
struct bnxt *bp = netdev_priv(dev);
700758
struct bnxt_link_info *link_info = &bp->link_info;
701-
u16 ethtool_speed;
702-
703-
cmd->supported = bnxt_fw_to_ethtool_support_spds(link_info);
759+
struct ethtool_link_settings *base = &lk_ksettings->base;
760+
u32 ethtool_speed;
704761

705-
if (link_info->support_auto_speeds)
706-
cmd->supported |= SUPPORTED_Autoneg;
762+
ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported);
763+
bnxt_fw_to_ethtool_support_spds(link_info, lk_ksettings);
707764

765+
ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising);
708766
if (link_info->autoneg) {
709-
cmd->advertising =
710-
bnxt_fw_to_ethtool_advertised_spds(link_info);
711-
cmd->advertising |= ADVERTISED_Autoneg;
712-
cmd->autoneg = AUTONEG_ENABLE;
767+
bnxt_fw_to_ethtool_advertised_spds(link_info, lk_ksettings);
768+
ethtool_link_ksettings_add_link_mode(lk_ksettings,
769+
advertising, Autoneg);
770+
base->autoneg = AUTONEG_ENABLE;
713771
if (link_info->phy_link_status == BNXT_LINK_LINK)
714-
cmd->lp_advertising =
715-
bnxt_fw_to_ethtool_lp_adv(link_info);
772+
bnxt_fw_to_ethtool_lp_adv(link_info, lk_ksettings);
716773
ethtool_speed = bnxt_fw_to_ethtool_speed(link_info->link_speed);
717774
if (!netif_carrier_ok(dev))
718-
cmd->duplex = DUPLEX_UNKNOWN;
775+
base->duplex = DUPLEX_UNKNOWN;
719776
else if (link_info->duplex & BNXT_LINK_DUPLEX_FULL)
720-
cmd->duplex = DUPLEX_FULL;
777+
base->duplex = DUPLEX_FULL;
721778
else
722-
cmd->duplex = DUPLEX_HALF;
779+
base->duplex = DUPLEX_HALF;
723780
} else {
724-
cmd->autoneg = AUTONEG_DISABLE;
725-
cmd->advertising = 0;
781+
base->autoneg = AUTONEG_DISABLE;
726782
ethtool_speed =
727783
bnxt_fw_to_ethtool_speed(link_info->req_link_speed);
728-
cmd->duplex = DUPLEX_HALF;
784+
base->duplex = DUPLEX_HALF;
729785
if (link_info->req_duplex == BNXT_LINK_DUPLEX_FULL)
730-
cmd->duplex = DUPLEX_FULL;
786+
base->duplex = DUPLEX_FULL;
731787
}
732-
ethtool_cmd_speed_set(cmd, ethtool_speed);
788+
base->speed = ethtool_speed;
733789

734-
cmd->port = PORT_NONE;
790+
base->port = PORT_NONE;
735791
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP) {
736-
cmd->port = PORT_TP;
737-
cmd->supported |= SUPPORTED_TP;
738-
cmd->advertising |= ADVERTISED_TP;
792+
base->port = PORT_TP;
793+
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
794+
TP);
795+
ethtool_link_ksettings_add_link_mode(lk_ksettings, advertising,
796+
TP);
739797
} else {
740-
cmd->supported |= SUPPORTED_FIBRE;
741-
cmd->advertising |= ADVERTISED_FIBRE;
798+
ethtool_link_ksettings_add_link_mode(lk_ksettings, supported,
799+
FIBRE);
800+
ethtool_link_ksettings_add_link_mode(lk_ksettings, advertising,
801+
FIBRE);
742802

743803
if (link_info->media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_DAC)
744-
cmd->port = PORT_DA;
804+
base->port = PORT_DA;
745805
else if (link_info->media_type ==
746806
PORT_PHY_QCFG_RESP_MEDIA_TYPE_FIBRE)
747-
cmd->port = PORT_FIBRE;
807+
base->port = PORT_FIBRE;
748808
}
749-
750-
if (link_info->transceiver ==
751-
PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL)
752-
cmd->transceiver = XCVR_INTERNAL;
753-
else
754-
cmd->transceiver = XCVR_EXTERNAL;
755-
cmd->phy_address = link_info->phy_addr;
809+
base->phy_address = link_info->phy_addr;
756810

757811
return 0;
758812
}
@@ -826,34 +880,22 @@ u16 bnxt_get_fw_auto_link_speeds(u32 advertising)
826880
return fw_speed_mask;
827881
}
828882

829-
static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
883+
static int bnxt_set_link_ksettings(struct net_device *dev,
884+
const struct ethtool_link_ksettings *lk_ksettings)
830885
{
831-
int rc = 0;
832886
struct bnxt *bp = netdev_priv(dev);
833887
struct bnxt_link_info *link_info = &bp->link_info;
888+
const struct ethtool_link_settings *base = &lk_ksettings->base;
834889
u32 speed, fw_advertising = 0;
835890
bool set_pause = false;
891+
int rc = 0;
836892

837893
if (!BNXT_SINGLE_PF(bp))
838-
return rc;
839-
840-
if (cmd->autoneg == AUTONEG_ENABLE) {
841-
u32 supported_spds =
842-
bnxt_fw_to_ethtool_support_adv_spds(link_info);
894+
return -EOPNOTSUPP;
843895

844-
if (!supported_spds) {
845-
netdev_err(dev, "Autoneg not supported\n");
846-
rc = -EINVAL;
847-
goto set_setting_exit;
848-
}
849-
if (cmd->advertising & ~(supported_spds | ADVERTISED_Autoneg |
850-
ADVERTISED_TP | ADVERTISED_FIBRE)) {
851-
netdev_err(dev, "Unsupported advertising mask (adv: 0x%x)\n",
852-
cmd->advertising);
853-
rc = -EINVAL;
854-
goto set_setting_exit;
855-
}
856-
fw_advertising = bnxt_get_fw_auto_link_speeds(cmd->advertising);
896+
if (base->autoneg == AUTONEG_ENABLE) {
897+
BNXT_ETHTOOL_TO_FW_SPDS(fw_advertising, lk_ksettings,
898+
advertising);
857899
link_info->autoneg |= BNXT_AUTONEG_SPEED;
858900
if (!fw_advertising)
859901
link_info->advertising = link_info->support_auto_speeds;
@@ -874,16 +916,12 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
874916
rc = -EINVAL;
875917
goto set_setting_exit;
876918
}
877-
/* TODO: currently don't support half duplex */
878-
if (cmd->duplex == DUPLEX_HALF) {
919+
if (base->duplex == DUPLEX_HALF) {
879920
netdev_err(dev, "HALF DUPLEX is not supported!\n");
880921
rc = -EINVAL;
881922
goto set_setting_exit;
882923
}
883-
/* If received a request for an unknown duplex, assume full*/
884-
if (cmd->duplex == DUPLEX_UNKNOWN)
885-
cmd->duplex = DUPLEX_FULL;
886-
speed = ethtool_cmd_speed(cmd);
924+
speed = base->speed;
887925
fw_speed = bnxt_get_fw_speed(dev, speed);
888926
if (!fw_speed) {
889927
rc = -EINVAL;
@@ -1629,8 +1667,8 @@ static int bnxt_get_module_eeprom(struct net_device *dev,
16291667
}
16301668

16311669
const struct ethtool_ops bnxt_ethtool_ops = {
1632-
.get_settings = bnxt_get_settings,
1633-
.set_settings = bnxt_set_settings,
1670+
.get_link_ksettings = bnxt_get_link_ksettings,
1671+
.set_link_ksettings = bnxt_set_link_ksettings,
16341672
.get_pauseparam = bnxt_get_pauseparam,
16351673
.set_pauseparam = bnxt_set_pauseparam,
16361674
.get_drvinfo = bnxt_get_drvinfo,

0 commit comments

Comments
 (0)