liquidio: Add the features to show FEC settings and set FEC settings
1. Add functions for get_fecparam and set_fecparam. 2. Modify lio_get_link_ksettings to display FEC setting. Signed-off-by: Weilin Chang <weilin.chang@cavium.com> Acked-by: Derek Chickles <derek.chickles@cavium.com> Signed-off-by: Felix Manlunas <felix.manlunas@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a4ebec033e
commit
75b2c206bb
|
@ -1654,3 +1654,151 @@ int liquidio_get_speed(struct lio *lio)
|
|||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int liquidio_set_fec(struct lio *lio, int on_off)
|
||||
{
|
||||
struct oct_nic_seapi_resp *resp;
|
||||
struct octeon_soft_command *sc;
|
||||
struct octeon_device *oct;
|
||||
union octnet_cmd *ncmd;
|
||||
int retval;
|
||||
u32 var;
|
||||
|
||||
oct = lio->oct_dev;
|
||||
|
||||
if (oct->props[lio->ifidx].fec == on_off)
|
||||
return 0;
|
||||
|
||||
if (!OCTEON_CN23XX_PF(oct)) {
|
||||
dev_err(&oct->pci_dev->dev, "%s: SET FEC only for PF\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (oct->speed_boot != 25) {
|
||||
dev_err(&oct->pci_dev->dev,
|
||||
"Set FEC only when link speed is 25G during insmod\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
|
||||
sizeof(struct oct_nic_seapi_resp), 0);
|
||||
|
||||
ncmd = sc->virtdptr;
|
||||
resp = sc->virtrptr;
|
||||
memset(resp, 0, sizeof(struct oct_nic_seapi_resp));
|
||||
|
||||
init_completion(&sc->complete);
|
||||
sc->sc_status = OCTEON_REQUEST_PENDING;
|
||||
|
||||
ncmd->u64 = 0;
|
||||
ncmd->s.cmd = SEAPI_CMD_FEC_SET;
|
||||
ncmd->s.param1 = on_off;
|
||||
/* SEAPI_CMD_FEC_DISABLE(0) or SEAPI_CMD_FEC_RS(1) */
|
||||
|
||||
octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
|
||||
|
||||
sc->iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
|
||||
octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
|
||||
OPCODE_NIC_UBOOT_CTL, 0, 0, 0);
|
||||
|
||||
retval = octeon_send_soft_command(oct, sc);
|
||||
if (retval == IQ_SEND_FAILED) {
|
||||
dev_info(&oct->pci_dev->dev, "Failed to send soft command\n");
|
||||
octeon_free_soft_command(oct, sc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
retval = wait_for_sc_completion_timeout(oct, sc, 0);
|
||||
if (retval)
|
||||
return (-EIO);
|
||||
|
||||
var = be32_to_cpu(resp->fec_setting);
|
||||
resp->fec_setting = var;
|
||||
if (var != on_off) {
|
||||
dev_err(&oct->pci_dev->dev,
|
||||
"Setting failed fec= %x, expect %x\n",
|
||||
var, on_off);
|
||||
oct->props[lio->ifidx].fec = var;
|
||||
if (resp->fec_setting == SEAPI_CMD_FEC_SET_RS)
|
||||
oct->props[lio->ifidx].fec = 1;
|
||||
else
|
||||
oct->props[lio->ifidx].fec = 0;
|
||||
}
|
||||
|
||||
WRITE_ONCE(sc->caller_is_done, true);
|
||||
|
||||
if (oct->props[lio->ifidx].fec !=
|
||||
oct->props[lio->ifidx].fec_boot) {
|
||||
dev_dbg(&oct->pci_dev->dev,
|
||||
"Reloade driver to chang fec to %s\n",
|
||||
oct->props[lio->ifidx].fec ? "on" : "off");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int liquidio_get_fec(struct lio *lio)
|
||||
{
|
||||
struct oct_nic_seapi_resp *resp;
|
||||
struct octeon_soft_command *sc;
|
||||
struct octeon_device *oct;
|
||||
union octnet_cmd *ncmd;
|
||||
int retval;
|
||||
u32 var;
|
||||
|
||||
oct = lio->oct_dev;
|
||||
|
||||
sc = octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
|
||||
sizeof(struct oct_nic_seapi_resp), 0);
|
||||
if (!sc)
|
||||
return -ENOMEM;
|
||||
|
||||
ncmd = sc->virtdptr;
|
||||
resp = sc->virtrptr;
|
||||
memset(resp, 0, sizeof(struct oct_nic_seapi_resp));
|
||||
|
||||
init_completion(&sc->complete);
|
||||
sc->sc_status = OCTEON_REQUEST_PENDING;
|
||||
|
||||
ncmd->u64 = 0;
|
||||
ncmd->s.cmd = SEAPI_CMD_FEC_GET;
|
||||
|
||||
octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3));
|
||||
|
||||
sc->iq_no = lio->linfo.txpciq[0].s.q_no;
|
||||
|
||||
octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
|
||||
OPCODE_NIC_UBOOT_CTL, 0, 0, 0);
|
||||
|
||||
retval = octeon_send_soft_command(oct, sc);
|
||||
if (retval == IQ_SEND_FAILED) {
|
||||
dev_info(&oct->pci_dev->dev,
|
||||
"%s: Failed to send soft command\n", __func__);
|
||||
octeon_free_soft_command(oct, sc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
retval = wait_for_sc_completion_timeout(oct, sc, 0);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
var = be32_to_cpu(resp->fec_setting);
|
||||
resp->fec_setting = var;
|
||||
if (resp->fec_setting == SEAPI_CMD_FEC_SET_RS)
|
||||
oct->props[lio->ifidx].fec = 1;
|
||||
else
|
||||
oct->props[lio->ifidx].fec = 0;
|
||||
|
||||
WRITE_ONCE(sc->caller_is_done, true);
|
||||
|
||||
if (oct->props[lio->ifidx].fec !=
|
||||
oct->props[lio->ifidx].fec_boot) {
|
||||
dev_dbg(&oct->pci_dev->dev,
|
||||
"Reloade driver to chang fec to %s\n",
|
||||
oct->props[lio->ifidx].fec ? "on" : "off");
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -244,6 +244,7 @@ static int lio_get_link_ksettings(struct net_device *netdev,
|
|||
linfo->link.s.if_mode == INTERFACE_MODE_XLAUI ||
|
||||
linfo->link.s.if_mode == INTERFACE_MODE_XFI) {
|
||||
dev_dbg(&oct->pci_dev->dev, "ecmd->base.transceiver is XCVR_EXTERNAL\n");
|
||||
ecmd->base.transceiver = XCVR_EXTERNAL;
|
||||
} else {
|
||||
dev_err(&oct->pci_dev->dev, "Unknown link interface mode: %d\n",
|
||||
linfo->link.s.if_mode);
|
||||
|
@ -277,10 +278,12 @@ static int lio_get_link_ksettings(struct net_device *netdev,
|
|||
10000baseCR_Full);
|
||||
}
|
||||
|
||||
if (oct->no_speed_setting == 0)
|
||||
if (oct->no_speed_setting == 0) {
|
||||
liquidio_get_speed(lio);
|
||||
else
|
||||
liquidio_get_fec(lio);
|
||||
} else {
|
||||
oct->speed_setting = 25;
|
||||
}
|
||||
|
||||
if (oct->speed_setting == 10) {
|
||||
ethtool_link_ksettings_add_link_mode
|
||||
|
@ -304,6 +307,24 @@ static int lio_get_link_ksettings(struct net_device *netdev,
|
|||
(ecmd, advertising,
|
||||
25000baseCR_Full);
|
||||
}
|
||||
|
||||
if (oct->no_speed_setting)
|
||||
break;
|
||||
|
||||
ethtool_link_ksettings_add_link_mode
|
||||
(ecmd, supported, FEC_RS);
|
||||
ethtool_link_ksettings_add_link_mode
|
||||
(ecmd, supported, FEC_NONE);
|
||||
/*FEC_OFF*/
|
||||
if (oct->props[lio->ifidx].fec == 1) {
|
||||
/* ETHTOOL_FEC_RS */
|
||||
ethtool_link_ksettings_add_link_mode
|
||||
(ecmd, advertising, FEC_RS);
|
||||
} else {
|
||||
/* ETHTOOL_FEC_OFF */
|
||||
ethtool_link_ksettings_add_link_mode
|
||||
(ecmd, advertising, FEC_NONE);
|
||||
}
|
||||
} else { /* VF */
|
||||
if (linfo->link.s.speed == 10000) {
|
||||
ethtool_link_ksettings_add_link_mode
|
||||
|
@ -3029,9 +3050,60 @@ static int lio_set_priv_flags(struct net_device *netdev, u32 flags)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lio_get_fecparam(struct net_device *netdev,
|
||||
struct ethtool_fecparam *fec)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
|
||||
fec->active_fec = ETHTOOL_FEC_NONE;
|
||||
fec->fec = ETHTOOL_FEC_NONE;
|
||||
|
||||
if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
|
||||
oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
|
||||
if (oct->no_speed_setting == 1)
|
||||
return 0;
|
||||
|
||||
liquidio_get_fec(lio);
|
||||
fec->fec = (ETHTOOL_FEC_RS | ETHTOOL_FEC_OFF);
|
||||
if (oct->props[lio->ifidx].fec == 1)
|
||||
fec->active_fec = ETHTOOL_FEC_RS;
|
||||
else
|
||||
fec->active_fec = ETHTOOL_FEC_OFF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lio_set_fecparam(struct net_device *netdev,
|
||||
struct ethtool_fecparam *fec)
|
||||
{
|
||||
struct lio *lio = GET_LIO(netdev);
|
||||
struct octeon_device *oct = lio->oct_dev;
|
||||
|
||||
if (oct->subsystem_id == OCTEON_CN2350_25GB_SUBSYS_ID ||
|
||||
oct->subsystem_id == OCTEON_CN2360_25GB_SUBSYS_ID) {
|
||||
if (oct->no_speed_setting == 1)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (fec->fec & ETHTOOL_FEC_OFF)
|
||||
liquidio_set_fec(lio, 0);
|
||||
else if (fec->fec & ETHTOOL_FEC_RS)
|
||||
liquidio_set_fec(lio, 1);
|
||||
else
|
||||
return -EOPNOTSUPP;
|
||||
} else {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ethtool_ops lio_ethtool_ops = {
|
||||
.get_link_ksettings = lio_get_link_ksettings,
|
||||
.set_link_ksettings = lio_set_link_ksettings,
|
||||
.get_fecparam = lio_get_fecparam,
|
||||
.set_fecparam = lio_set_fecparam,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_drvinfo = lio_get_drvinfo,
|
||||
.get_ringparam = lio_ethtool_get_ringparam,
|
||||
|
|
|
@ -3761,6 +3761,14 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
|
|||
octeon_dev->speed_setting = 10;
|
||||
}
|
||||
octeon_dev->speed_boot = octeon_dev->speed_setting;
|
||||
|
||||
/* don't read FEC setting if unsupported by f/w (see above) */
|
||||
if (octeon_dev->speed_boot == 25 &&
|
||||
!octeon_dev->no_speed_setting) {
|
||||
liquidio_get_fec(lio);
|
||||
octeon_dev->props[lio->ifidx].fec_boot =
|
||||
octeon_dev->props[lio->ifidx].fec;
|
||||
}
|
||||
}
|
||||
|
||||
devlink = devlink_alloc(&liquidio_devlink_ops,
|
||||
|
|
|
@ -260,6 +260,11 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry,
|
|||
|
||||
#define OCTNET_CMD_FAIL 0x1
|
||||
|
||||
#define SEAPI_CMD_FEC_SET 0x0
|
||||
#define SEAPI_CMD_FEC_SET_DISABLE 0x0
|
||||
#define SEAPI_CMD_FEC_SET_RS 0x1
|
||||
#define SEAPI_CMD_FEC_GET 0x1
|
||||
|
||||
#define SEAPI_CMD_SPEED_SET 0x2
|
||||
#define SEAPI_CMD_SPEED_GET 0x3
|
||||
|
||||
|
|
|
@ -316,6 +316,8 @@ struct octdev_props {
|
|||
* device pointer (used for OS specific calls).
|
||||
*/
|
||||
int rx_on;
|
||||
int fec;
|
||||
int fec_boot;
|
||||
int napi_enabled;
|
||||
int gmxport;
|
||||
struct net_device *netdev;
|
||||
|
|
|
@ -84,7 +84,10 @@ struct oct_nic_stats_ctrl {
|
|||
|
||||
struct oct_nic_seapi_resp {
|
||||
u64 rh;
|
||||
u32 speed;
|
||||
union {
|
||||
u32 fec_setting;
|
||||
u32 speed;
|
||||
};
|
||||
u64 status;
|
||||
};
|
||||
|
||||
|
@ -236,6 +239,8 @@ int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_qs);
|
|||
|
||||
int liquidio_get_speed(struct lio *lio);
|
||||
int liquidio_set_speed(struct lio *lio, int speed);
|
||||
int liquidio_get_fec(struct lio *lio);
|
||||
int liquidio_set_fec(struct lio *lio, int on_off);
|
||||
|
||||
/**
|
||||
* \brief Net device change_mtu
|
||||
|
|
Loading…
Reference in New Issue