Commit 821de68c authored by Yu Xiao's avatar Yu Xiao Committed by David S. Miller

nfp: ethtool: fix the bug of setting unsupported port speed

Unsupported port speed can be set and cause error. Now fixing it
and return an error if setting unsupported speed.

This fix depends on the following, which was included in v6.2-rc1:
commit a61474c4 ("nfp: ethtool: support reporting link modes").

Fixes: 7c698737 ("nfp: add support for .set_link_ksettings()")
Signed-off-by: default avatarYu Xiao <yu.xiao@corigine.com>
Signed-off-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c11204c7
......@@ -293,35 +293,131 @@ nfp_net_set_fec_link_mode(struct nfp_eth_table_port *eth_port,
}
}
static const u16 nfp_eth_media_table[] = {
[NFP_MEDIA_1000BASE_CX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
[NFP_MEDIA_1000BASE_KX] = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
[NFP_MEDIA_10GBASE_KX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
[NFP_MEDIA_10GBASE_KR] = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
[NFP_MEDIA_10GBASE_CX4] = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
[NFP_MEDIA_10GBASE_CR] = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
[NFP_MEDIA_10GBASE_SR] = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
[NFP_MEDIA_10GBASE_ER] = ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
[NFP_MEDIA_25GBASE_KR] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
[NFP_MEDIA_25GBASE_KR_S] = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
[NFP_MEDIA_25GBASE_CR] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
[NFP_MEDIA_25GBASE_CR_S] = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
[NFP_MEDIA_25GBASE_SR] = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
[NFP_MEDIA_40GBASE_CR4] = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
[NFP_MEDIA_40GBASE_KR4] = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
[NFP_MEDIA_40GBASE_SR4] = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
[NFP_MEDIA_40GBASE_LR4] = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
[NFP_MEDIA_50GBASE_KR] = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
[NFP_MEDIA_50GBASE_SR] = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
[NFP_MEDIA_50GBASE_CR] = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
[NFP_MEDIA_50GBASE_LR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
[NFP_MEDIA_50GBASE_ER] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
[NFP_MEDIA_50GBASE_FR] = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
[NFP_MEDIA_100GBASE_KR4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
[NFP_MEDIA_100GBASE_SR4] = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
[NFP_MEDIA_100GBASE_CR4] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
[NFP_MEDIA_100GBASE_KP4] = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
[NFP_MEDIA_100GBASE_CR10] = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
static const struct nfp_eth_media_link_mode {
u16 ethtool_link_mode;
u16 speed;
} nfp_eth_media_table[NFP_MEDIA_LINK_MODES_NUMBER] = {
[NFP_MEDIA_1000BASE_CX] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
.speed = NFP_SPEED_1G,
},
[NFP_MEDIA_1000BASE_KX] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
.speed = NFP_SPEED_1G,
},
[NFP_MEDIA_10GBASE_KX4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
.speed = NFP_SPEED_10G,
},
[NFP_MEDIA_10GBASE_KR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
.speed = NFP_SPEED_10G,
},
[NFP_MEDIA_10GBASE_CX4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
.speed = NFP_SPEED_10G,
},
[NFP_MEDIA_10GBASE_CR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
.speed = NFP_SPEED_10G,
},
[NFP_MEDIA_10GBASE_SR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
.speed = NFP_SPEED_10G,
},
[NFP_MEDIA_10GBASE_ER] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
.speed = NFP_SPEED_10G,
},
[NFP_MEDIA_25GBASE_KR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
.speed = NFP_SPEED_25G,
},
[NFP_MEDIA_25GBASE_KR_S] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
.speed = NFP_SPEED_25G,
},
[NFP_MEDIA_25GBASE_CR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
.speed = NFP_SPEED_25G,
},
[NFP_MEDIA_25GBASE_CR_S] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
.speed = NFP_SPEED_25G,
},
[NFP_MEDIA_25GBASE_SR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
.speed = NFP_SPEED_25G,
},
[NFP_MEDIA_40GBASE_CR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
.speed = NFP_SPEED_40G,
},
[NFP_MEDIA_40GBASE_KR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
.speed = NFP_SPEED_40G,
},
[NFP_MEDIA_40GBASE_SR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
.speed = NFP_SPEED_40G,
},
[NFP_MEDIA_40GBASE_LR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
.speed = NFP_SPEED_40G,
},
[NFP_MEDIA_50GBASE_KR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
.speed = NFP_SPEED_50G,
},
[NFP_MEDIA_50GBASE_SR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
.speed = NFP_SPEED_50G,
},
[NFP_MEDIA_50GBASE_CR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
.speed = NFP_SPEED_50G,
},
[NFP_MEDIA_50GBASE_LR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
.speed = NFP_SPEED_50G,
},
[NFP_MEDIA_50GBASE_ER] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
.speed = NFP_SPEED_50G,
},
[NFP_MEDIA_50GBASE_FR] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
.speed = NFP_SPEED_50G,
},
[NFP_MEDIA_100GBASE_KR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
.speed = NFP_SPEED_100G,
},
[NFP_MEDIA_100GBASE_SR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
.speed = NFP_SPEED_100G,
},
[NFP_MEDIA_100GBASE_CR4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
.speed = NFP_SPEED_100G,
},
[NFP_MEDIA_100GBASE_KP4] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
.speed = NFP_SPEED_100G,
},
[NFP_MEDIA_100GBASE_CR10] = {
.ethtool_link_mode = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
.speed = NFP_SPEED_100G,
},
};
static const unsigned int nfp_eth_speed_map[NFP_SUP_SPEED_NUMBER] = {
[NFP_SPEED_1G] = SPEED_1000,
[NFP_SPEED_10G] = SPEED_10000,
[NFP_SPEED_25G] = SPEED_25000,
[NFP_SPEED_40G] = SPEED_40000,
[NFP_SPEED_50G] = SPEED_50000,
[NFP_SPEED_100G] = SPEED_100000,
};
static void nfp_add_media_link_mode(struct nfp_port *port,
......@@ -334,8 +430,12 @@ static void nfp_add_media_link_mode(struct nfp_port *port,
};
struct nfp_cpp *cpp = port->app->cpp;
if (nfp_eth_read_media(cpp, &ethm))
if (nfp_eth_read_media(cpp, &ethm)) {
bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
return;
}
bitmap_zero(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
for (u32 i = 0; i < 2; i++) {
supported_modes[i] = le64_to_cpu(ethm.supported_modes[i]);
......@@ -344,20 +444,26 @@ static void nfp_add_media_link_mode(struct nfp_port *port,
for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) {
if (i < 64) {
if (supported_modes[0] & BIT_ULL(i))
__set_bit(nfp_eth_media_table[i],
if (supported_modes[0] & BIT_ULL(i)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap);
}
if (advertised_modes[0] & BIT_ULL(i))
__set_bit(nfp_eth_media_table[i],
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising);
} else {
if (supported_modes[1] & BIT_ULL(i - 64))
__set_bit(nfp_eth_media_table[i],
if (supported_modes[1] & BIT_ULL(i - 64)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap);
}
if (advertised_modes[1] & BIT_ULL(i - 64))
__set_bit(nfp_eth_media_table[i],
__set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising);
}
}
......@@ -468,6 +574,22 @@ nfp_net_set_link_ksettings(struct net_device *netdev,
if (cmd->base.speed != SPEED_UNKNOWN) {
u32 speed = cmd->base.speed / eth_port->lanes;
bool is_supported = false;
for (u32 i = 0; i < NFP_SUP_SPEED_NUMBER; i++) {
if (cmd->base.speed == nfp_eth_speed_map[i] &&
test_bit(i, port->speed_bitmap)) {
is_supported = true;
break;
}
}
if (!is_supported) {
netdev_err(netdev, "Speed %u is not supported.\n",
cmd->base.speed);
err = -EINVAL;
goto err_bad_set;
}
if (req_aneg) {
netdev_err(netdev, "Speed changing is not allowed when working on autoneg mode.\n");
......
......@@ -38,6 +38,16 @@ enum nfp_port_flags {
NFP_PORT_CHANGED = 0,
};
enum {
NFP_SPEED_1G,
NFP_SPEED_10G,
NFP_SPEED_25G,
NFP_SPEED_40G,
NFP_SPEED_50G,
NFP_SPEED_100G,
NFP_SUP_SPEED_NUMBER
};
/**
* struct nfp_port - structure representing NFP port
* @netdev: backpointer to associated netdev
......@@ -52,6 +62,7 @@ enum nfp_port_flags {
* @eth_forced: for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change
* @eth_port: for %NFP_PORT_PHYS_PORT translated ETH Table port entry
* @eth_stats: for %NFP_PORT_PHYS_PORT MAC stats if available
* @speed_bitmap: for %NFP_PORT_PHYS_PORT supported speed bitmap
* @pf_id: for %NFP_PORT_PF_PORT, %NFP_PORT_VF_PORT ID of the PCI PF (0-3)
* @vf_id: for %NFP_PORT_VF_PORT ID of the PCI VF within @pf_id
* @pf_split: for %NFP_PORT_PF_PORT %true if PCI PF has more than one vNIC
......@@ -78,6 +89,7 @@ struct nfp_port {
bool eth_forced;
struct nfp_eth_table_port *eth_port;
u8 __iomem *eth_stats;
DECLARE_BITMAP(speed_bitmap, NFP_SUP_SPEED_NUMBER);
};
/* NFP_PORT_PF_PORT, NFP_PORT_VF_PORT */
struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment