net/cxgbe: support configuring link FEC
Add ethdev ops to query and configure link FEC. Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
This commit is contained in:
parent
a83041b1e9
commit
62aafe0358
@ -331,6 +331,8 @@ static inline int t4_link_l1cfg_ns(struct port_info *pi, u32 caps)
|
||||
int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps);
|
||||
int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
|
||||
u8 pause_rx, u32 *new_caps);
|
||||
int t4_set_link_fec(struct port_info *pi, u8 fec_rs, u8 fec_baser,
|
||||
u8 fec_none, u32 *new_caps);
|
||||
unsigned int t4_fwcap_to_speed(u32 caps);
|
||||
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
|
||||
const unsigned short *alpha, const unsigned short *beta);
|
||||
|
@ -4473,6 +4473,76 @@ int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t4_set_link_fec(struct port_info *pi, u8 fec_rs, u8 fec_baser,
|
||||
u8 fec_none, u32 *new_caps)
|
||||
{
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 max_speed, caps = *new_caps;
|
||||
|
||||
if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* Link might be down. In that case consider the max
|
||||
* speed advertised
|
||||
*/
|
||||
max_speed = t4_fwcap_to_speed(lc->link_caps);
|
||||
if (!max_speed)
|
||||
max_speed = t4_fwcap_to_speed(lc->acaps);
|
||||
|
||||
caps &= ~V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC);
|
||||
if (fec_rs) {
|
||||
switch (max_speed) {
|
||||
case 100000:
|
||||
case 25000:
|
||||
caps |= FW_PORT_CAP32_FEC_RS;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (fec_baser) {
|
||||
switch (max_speed) {
|
||||
case 50000:
|
||||
case 25000:
|
||||
caps |= FW_PORT_CAP32_FEC_BASER_RS;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
if (fec_none)
|
||||
caps |= FW_PORT_CAP32_FEC_NO_FEC;
|
||||
|
||||
if (!(caps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC))) {
|
||||
/* No explicit encoding is requested.
|
||||
* So, default back to AUTO.
|
||||
*/
|
||||
switch (max_speed) {
|
||||
case 100000:
|
||||
caps |= FW_PORT_CAP32_FEC_RS |
|
||||
FW_PORT_CAP32_FEC_NO_FEC;
|
||||
break;
|
||||
case 50000:
|
||||
caps |= FW_PORT_CAP32_FEC_BASER_RS |
|
||||
FW_PORT_CAP32_FEC_NO_FEC;
|
||||
break;
|
||||
case 25000:
|
||||
caps |= FW_PORT_CAP32_FEC_RS |
|
||||
FW_PORT_CAP32_FEC_BASER_RS |
|
||||
FW_PORT_CAP32_FEC_NO_FEC;
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
*new_caps = caps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_handle_get_port_info - process a FW reply message
|
||||
* @pi: the port info
|
||||
@ -4630,6 +4700,7 @@ void t4_reset_link_config(struct adapter *adap, int idx)
|
||||
void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
|
||||
u8 mdio_addr, u8 port_type, u8 mod_type)
|
||||
{
|
||||
u8 fec_rs = 0, fec_baser = 0, fec_none = 0;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
|
||||
lc->pcaps = pcaps;
|
||||
@ -4650,6 +4721,23 @@ void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
|
||||
if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
|
||||
lc->admin_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
|
||||
|
||||
/* Reset FEC caps to default values */
|
||||
if (lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)) {
|
||||
if (lc->acaps & FW_PORT_CAP32_FEC_RS)
|
||||
fec_rs = 1;
|
||||
else if (lc->acaps & FW_PORT_CAP32_FEC_BASER_RS)
|
||||
fec_baser = 1;
|
||||
else
|
||||
fec_none = 1;
|
||||
|
||||
lc->admin_caps &= ~V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC);
|
||||
t4_set_link_fec(pi, fec_rs, fec_baser, fec_none,
|
||||
&lc->admin_caps);
|
||||
}
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC)
|
||||
lc->admin_caps &= ~FW_PORT_CAP32_FORCE_FEC;
|
||||
|
||||
/* Reset MDI to AUTO */
|
||||
if (lc->pcaps & FW_PORT_CAP32_MDIAUTO) {
|
||||
lc->admin_caps &= ~V_FW_PORT_CAP32_MDI(M_FW_PORT_CAP32_MDI);
|
||||
|
@ -1615,7 +1615,9 @@ struct fw_vi_stats_cmd {
|
||||
#define FW_PORT_CAP32_MDIAUTO 0x00400000UL
|
||||
#define FW_PORT_CAP32_FEC_RS 0x00800000UL
|
||||
#define FW_PORT_CAP32_FEC_BASER_RS 0x01000000UL
|
||||
#define FW_PORT_CAP32_FEC_NO_FEC 0x02000000UL
|
||||
#define FW_PORT_CAP32_FORCE_PAUSE 0x10000000UL
|
||||
#define FW_PORT_CAP32_FORCE_FEC 0x20000000UL
|
||||
|
||||
#define S_FW_PORT_CAP32_SPEED 0
|
||||
#define M_FW_PORT_CAP32_SPEED 0xfff
|
||||
@ -1641,6 +1643,10 @@ enum fw_port_mdi32 {
|
||||
#define G_FW_PORT_CAP32_MDI(x) \
|
||||
(((x) >> S_FW_PORT_CAP32_MDI) & M_FW_PORT_CAP32_MDI)
|
||||
|
||||
#define S_FW_PORT_CAP32_FEC 23
|
||||
#define M_FW_PORT_CAP32_FEC 0x1f
|
||||
#define V_FW_PORT_CAP32_FEC(x) ((x) << S_FW_PORT_CAP32_FEC)
|
||||
|
||||
enum fw_port_action {
|
||||
FW_PORT_ACTION_L1_CFG32 = 0x0009,
|
||||
FW_PORT_ACTION_GET_PORT_INFO32 = 0x000a,
|
||||
|
@ -1193,6 +1193,125 @@ int cxgbe_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxgbe_fec_get_capa_speed_to_fec(struct link_config *lc,
|
||||
struct rte_eth_fec_capa *capa_arr)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_SPEED_100G) {
|
||||
if (capa_arr) {
|
||||
capa_arr[num].speed = ETH_SPEED_NUM_100G;
|
||||
capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
|
||||
RTE_ETH_FEC_MODE_CAPA_MASK(RS);
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_SPEED_50G) {
|
||||
if (capa_arr) {
|
||||
capa_arr[num].speed = ETH_SPEED_NUM_50G;
|
||||
capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
|
||||
RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_SPEED_25G) {
|
||||
if (capa_arr) {
|
||||
capa_arr[num].speed = ETH_SPEED_NUM_25G;
|
||||
capa_arr[num].capa = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC) |
|
||||
RTE_ETH_FEC_MODE_CAPA_MASK(BASER) |
|
||||
RTE_ETH_FEC_MODE_CAPA_MASK(RS);
|
||||
}
|
||||
num++;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static int cxgbe_fec_get_capability(struct rte_eth_dev *dev,
|
||||
struct rte_eth_fec_capa *speed_fec_capa,
|
||||
unsigned int num)
|
||||
{
|
||||
struct port_info *pi = dev->data->dev_private;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u8 num_entries;
|
||||
|
||||
if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
num_entries = cxgbe_fec_get_capa_speed_to_fec(lc, NULL);
|
||||
if (!speed_fec_capa || num < num_entries)
|
||||
return num_entries;
|
||||
|
||||
return cxgbe_fec_get_capa_speed_to_fec(lc, speed_fec_capa);
|
||||
}
|
||||
|
||||
static int cxgbe_fec_get(struct rte_eth_dev *dev, uint32_t *fec_capa)
|
||||
{
|
||||
struct port_info *pi = dev->data->dev_private;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 fec_caps = 0, caps = lc->link_caps;
|
||||
|
||||
if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (caps & FW_PORT_CAP32_FEC_RS)
|
||||
fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
|
||||
else if (caps & FW_PORT_CAP32_FEC_BASER_RS)
|
||||
fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
|
||||
else
|
||||
fec_caps = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
|
||||
|
||||
*fec_capa = fec_caps;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cxgbe_fec_set(struct rte_eth_dev *dev, uint32_t fec_capa)
|
||||
{
|
||||
struct port_info *pi = dev->data->dev_private;
|
||||
u8 fec_rs = 0, fec_baser = 0, fec_none = 0;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 new_caps = lc->admin_caps;
|
||||
int ret;
|
||||
|
||||
if (!(lc->pcaps & V_FW_PORT_CAP32_FEC(M_FW_PORT_CAP32_FEC)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!fec_capa)
|
||||
return -EINVAL;
|
||||
|
||||
if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(AUTO))
|
||||
goto set_fec;
|
||||
|
||||
if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC))
|
||||
fec_none = 1;
|
||||
|
||||
if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(BASER))
|
||||
fec_baser = 1;
|
||||
|
||||
if (fec_capa & RTE_ETH_FEC_MODE_CAPA_MASK(RS))
|
||||
fec_rs = 1;
|
||||
|
||||
set_fec:
|
||||
ret = t4_set_link_fec(pi, fec_rs, fec_baser, fec_none, &new_caps);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_FORCE_FEC)
|
||||
new_caps |= FW_PORT_CAP32_FORCE_FEC;
|
||||
else
|
||||
new_caps &= ~FW_PORT_CAP32_FORCE_FEC;
|
||||
|
||||
if (new_caps != lc->admin_caps) {
|
||||
ret = t4_link_l1cfg(pi, new_caps);
|
||||
if (ret == 0)
|
||||
lc->admin_caps = new_caps;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct eth_dev_ops cxgbe_eth_dev_ops = {
|
||||
.dev_start = cxgbe_dev_start,
|
||||
.dev_stop = cxgbe_dev_stop,
|
||||
@ -1230,6 +1349,9 @@ static const struct eth_dev_ops cxgbe_eth_dev_ops = {
|
||||
.mac_addr_set = cxgbe_mac_addr_set,
|
||||
.reta_update = cxgbe_dev_rss_reta_update,
|
||||
.reta_query = cxgbe_dev_rss_reta_query,
|
||||
.fec_get_capability = cxgbe_fec_get_capability,
|
||||
.fec_get = cxgbe_fec_get,
|
||||
.fec_set = cxgbe_fec_set,
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user