Skip to content

Commit

Permalink
bnxt_en: Implement ethtool set_fec_param() method.
Browse files Browse the repository at this point in the history
This feature allows the user to set the different FEC modes on the NIC
port.  Any new setting will take effect immediately after a link toggle.

Reviewed-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and David S. Miller committed Sep 27, 2020
1 parent 2046e3c commit ccd6a9d
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -8890,7 +8890,7 @@ static bool bnxt_support_dropped(u16 advertising, u16 supported)
return ((supported | diff) != supported);
}

static int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
int bnxt_update_link(struct bnxt *bp, bool chng_link_state)
{
int rc = 0;
struct bnxt_link_info *link_info = &bp->link_info;
Expand Down
44 changes: 44 additions & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1259,6 +1259,49 @@ struct bnxt_link_info {
struct hwrm_port_phy_qcfg_output phy_qcfg_resp;
};

#define BNXT_FEC_RS544_ON \
(PORT_PHY_CFG_REQ_FLAGS_FEC_RS544_1XN_ENABLE | \
PORT_PHY_CFG_REQ_FLAGS_FEC_RS544_IEEE_ENABLE)

#define BNXT_FEC_RS544_OFF \
(PORT_PHY_CFG_REQ_FLAGS_FEC_RS544_1XN_DISABLE | \
PORT_PHY_CFG_REQ_FLAGS_FEC_RS544_IEEE_DISABLE)

#define BNXT_FEC_RS272_ON \
(PORT_PHY_CFG_REQ_FLAGS_FEC_RS272_1XN_ENABLE | \
PORT_PHY_CFG_REQ_FLAGS_FEC_RS272_IEEE_ENABLE)

#define BNXT_FEC_RS272_OFF \
(PORT_PHY_CFG_REQ_FLAGS_FEC_RS272_1XN_DISABLE | \
PORT_PHY_CFG_REQ_FLAGS_FEC_RS272_IEEE_DISABLE)

#define BNXT_PAM4_SUPPORTED(link_info) \
((link_info)->support_pam4_speeds)

#define BNXT_FEC_RS_ON(link_info) \
(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_ENABLE | \
PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE | \
(BNXT_PAM4_SUPPORTED(link_info) ? \
(BNXT_FEC_RS544_ON | BNXT_FEC_RS272_OFF) : 0))

#define BNXT_FEC_LLRS_ON \
(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_ENABLE | \
PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE | \
BNXT_FEC_RS272_ON | BNXT_FEC_RS544_OFF)

#define BNXT_FEC_RS_OFF(link_info) \
(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE91_DISABLE | \
(BNXT_PAM4_SUPPORTED(link_info) ? \
(BNXT_FEC_RS544_OFF | BNXT_FEC_RS272_OFF) : 0))

#define BNXT_FEC_BASE_R_ON(link_info) \
(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_ENABLE | \
BNXT_FEC_RS_OFF(link_info))

#define BNXT_FEC_ALL_OFF(link_info) \
(PORT_PHY_CFG_REQ_FLAGS_FEC_CLAUSE74_DISABLE | \
BNXT_FEC_RS_OFF(link_info))

#define BNXT_MAX_QUEUE 8

struct bnxt_queue_info {
Expand Down Expand Up @@ -2125,6 +2168,7 @@ int bnxt_get_avail_msix(struct bnxt *bp, int num);
int bnxt_reserve_rings(struct bnxt *bp, bool irq_re_init);
void bnxt_tx_disable(struct bnxt *bp);
void bnxt_tx_enable(struct bnxt *bp);
int bnxt_update_link(struct bnxt *bp, bool chng_link_state);
int bnxt_hwrm_set_pause(struct bnxt *);
int bnxt_hwrm_set_link_setting(struct bnxt *, bool, bool);
int bnxt_hwrm_alloc_wol_fltr(struct bnxt *bp);
Expand Down
62 changes: 62 additions & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1924,6 +1924,67 @@ static int bnxt_get_fecparam(struct net_device *dev,
return 0;
}

static u32 bnxt_ethtool_forced_fec_to_fw(struct bnxt_link_info *link_info,
u32 fec)
{
u32 fw_fec = PORT_PHY_CFG_REQ_FLAGS_FEC_AUTONEG_DISABLE;

if (fec & ETHTOOL_FEC_BASER)
fw_fec |= BNXT_FEC_BASE_R_ON(link_info);
else if (fec & ETHTOOL_FEC_RS)
fw_fec |= BNXT_FEC_RS_ON(link_info);
else if (fec & ETHTOOL_FEC_LLRS)
fw_fec |= BNXT_FEC_LLRS_ON;
return fw_fec;
}

static int bnxt_set_fecparam(struct net_device *dev,
struct ethtool_fecparam *fecparam)
{
struct hwrm_port_phy_cfg_input req = {0};
struct bnxt *bp = netdev_priv(dev);
struct bnxt_link_info *link_info;
u32 new_cfg, fec = fecparam->fec;
u16 fec_cfg;
int rc;

link_info = &bp->link_info;
fec_cfg = link_info->fec_cfg;
if (fec_cfg & BNXT_FEC_NONE)
return -EOPNOTSUPP;

if (fec & ETHTOOL_FEC_OFF) {
new_cfg = PORT_PHY_CFG_REQ_FLAGS_FEC_AUTONEG_DISABLE |
BNXT_FEC_ALL_OFF(link_info);
goto apply_fec;
}
if (((fec & ETHTOOL_FEC_AUTO) && !(fec_cfg & BNXT_FEC_AUTONEG_CAP)) ||
((fec & ETHTOOL_FEC_RS) && !(fec_cfg & BNXT_FEC_ENC_RS_CAP)) ||
((fec & ETHTOOL_FEC_LLRS) && !(fec_cfg & BNXT_FEC_ENC_LLRS_CAP)) ||
((fec & ETHTOOL_FEC_BASER) && !(fec_cfg & BNXT_FEC_ENC_BASE_R_CAP)))
return -EINVAL;

if (fec & ETHTOOL_FEC_AUTO) {
if (!link_info->autoneg)
return -EINVAL;
new_cfg = PORT_PHY_CFG_REQ_FLAGS_FEC_AUTONEG_ENABLE;
} else {
new_cfg = bnxt_ethtool_forced_fec_to_fw(link_info, fec);
}

apply_fec:
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_PHY_CFG, -1, -1);
req.flags = cpu_to_le32(new_cfg | PORT_PHY_CFG_REQ_FLAGS_RESET_PHY);
rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
/* update current settings */
if (!rc) {
mutex_lock(&bp->link_lock);
bnxt_update_link(bp, false);
mutex_unlock(&bp->link_lock);
}
return rc;
}

static void bnxt_get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
Expand Down Expand Up @@ -3830,6 +3891,7 @@ const struct ethtool_ops bnxt_ethtool_ops = {
.get_link_ksettings = bnxt_get_link_ksettings,
.set_link_ksettings = bnxt_set_link_ksettings,
.get_fecparam = bnxt_get_fecparam,
.set_fecparam = bnxt_set_fecparam,
.get_pause_stats = bnxt_get_pause_stats,
.get_pauseparam = bnxt_get_pauseparam,
.set_pauseparam = bnxt_set_pauseparam,
Expand Down

0 comments on commit ccd6a9d

Please sign in to comment.