Commit a731a43e authored by Yinjun Zhang's avatar Yinjun Zhang Committed by Jakub Kicinski

nfp: improve link modes reading process

Avoid reading link modes from management firmware every time when
`ethtool_get_link_ksettings` is called, only communicate with
management firmware when necessary like we do for eth_table info.

This change can ease the situation that when large number of vlan
sub-interfaces are created and their information is requested by
some monitoring process like PCP [1] through ethool ioctl frequently.

[1] https://pcp.ioSigned-off-by: default avatarYinjun Zhang <yinjun.zhang@corigine.com>
Acked-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarLouis Peens <louis.peens@corigine.com>
Reviewed-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Link: https://lore.kernel.org/r/20230509075817.10566-1-louis.peens@corigine.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 94e86ef1
...@@ -436,49 +436,41 @@ static void nfp_add_media_link_mode(struct nfp_port *port, ...@@ -436,49 +436,41 @@ static void nfp_add_media_link_mode(struct nfp_port *port,
struct nfp_eth_table_port *eth_port, struct nfp_eth_table_port *eth_port,
struct ethtool_link_ksettings *cmd) struct ethtool_link_ksettings *cmd)
{ {
u64 supported_modes[2], advertised_modes[2];
struct nfp_eth_media_buf ethm = {
.eth_index = eth_port->eth_index,
};
struct nfp_cpp *cpp = port->app->cpp;
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); 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]);
advertised_modes[i] = le64_to_cpu(ethm.advertised_modes[i]);
}
for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) { for (u32 i = 0; i < NFP_MEDIA_LINK_MODES_NUMBER; i++) {
if (i < 64) { if (i < 64) {
if (supported_modes[0] & BIT_ULL(i)) { if (eth_port->link_modes_supp[0] & BIT_ULL(i)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode, __set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported); cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed, __set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap); port->speed_bitmap);
} }
if (advertised_modes[0] & BIT_ULL(i)) if (eth_port->link_modes_ad[0] & BIT_ULL(i))
__set_bit(nfp_eth_media_table[i].ethtool_link_mode, __set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising); cmd->link_modes.advertising);
} else { } else {
if (supported_modes[1] & BIT_ULL(i - 64)) { if (eth_port->link_modes_supp[1] & BIT_ULL(i - 64)) {
__set_bit(nfp_eth_media_table[i].ethtool_link_mode, __set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.supported); cmd->link_modes.supported);
__set_bit(nfp_eth_media_table[i].speed, __set_bit(nfp_eth_media_table[i].speed,
port->speed_bitmap); port->speed_bitmap);
} }
if (advertised_modes[1] & BIT_ULL(i - 64)) if (eth_port->link_modes_ad[1] & BIT_ULL(i - 64))
__set_bit(nfp_eth_media_table[i].ethtool_link_mode, __set_bit(nfp_eth_media_table[i].ethtool_link_mode,
cmd->link_modes.advertising); cmd->link_modes.advertising);
} }
} }
/* We take all speeds as supported when it fails to read
* link modes due to old management firmware that doesn't
* support link modes reading or error occurring, so that
* speed change of this port is allowed.
*/
if (bitmap_empty(port->speed_bitmap, NFP_SUP_SPEED_NUMBER))
bitmap_fill(port->speed_bitmap, NFP_SUP_SPEED_NUMBER);
} }
/** /**
......
...@@ -196,6 +196,9 @@ enum nfp_ethtool_link_mode_list { ...@@ -196,6 +196,9 @@ enum nfp_ethtool_link_mode_list {
* subports) * subports)
* @ports.is_split: is interface part of a split port * @ports.is_split: is interface part of a split port
* @ports.fec_modes_supported: bitmap of FEC modes supported * @ports.fec_modes_supported: bitmap of FEC modes supported
*
* @ports.link_modes_supp: bitmap of link modes supported
* @ports.link_modes_ad: bitmap of link modes advertised
*/ */
struct nfp_eth_table { struct nfp_eth_table {
unsigned int count; unsigned int count;
...@@ -235,6 +238,9 @@ struct nfp_eth_table { ...@@ -235,6 +238,9 @@ struct nfp_eth_table {
bool is_split; bool is_split;
unsigned int fec_modes_supported; unsigned int fec_modes_supported;
u64 link_modes_supp[2];
u64 link_modes_ad[2];
} ports[]; } ports[];
}; };
...@@ -313,7 +319,6 @@ struct nfp_eth_media_buf { ...@@ -313,7 +319,6 @@ struct nfp_eth_media_buf {
}; };
int nfp_nsp_read_media(struct nfp_nsp *state, void *buf, unsigned int size); int nfp_nsp_read_media(struct nfp_nsp *state, void *buf, unsigned int size);
int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm);
#define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */ #define NFP_NSP_VERSION_BUFSZ 1024 /* reasonable size, not in the ABI */
......
...@@ -227,6 +227,30 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry) ...@@ -227,6 +227,30 @@ nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry)
entry->port_type = PORT_DA; entry->port_type = PORT_DA;
} }
static void
nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_nsp *nsp, struct nfp_eth_table_port *entry)
{
struct nfp_eth_media_buf ethm = {
.eth_index = entry->eth_index,
};
unsigned int i;
int ret;
if (!nfp_nsp_has_read_media(nsp))
return;
ret = nfp_nsp_read_media(nsp, &ethm, sizeof(ethm));
if (ret) {
nfp_err(cpp, "Reading media link modes failed: %d\n", ret);
return;
}
for (i = 0; i < 2; i++) {
entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]);
entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]);
}
}
/** /**
* nfp_eth_read_ports() - retrieve port information * nfp_eth_read_ports() - retrieve port information
* @cpp: NFP CPP handle * @cpp: NFP CPP handle
...@@ -293,8 +317,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) ...@@ -293,8 +317,10 @@ __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
&table->ports[j++]); &table->ports[j++]);
nfp_eth_calc_port_geometry(cpp, table); nfp_eth_calc_port_geometry(cpp, table);
for (i = 0; i < table->count; i++) for (i = 0; i < table->count; i++) {
nfp_eth_calc_port_type(cpp, &table->ports[i]); nfp_eth_calc_port_type(cpp, &table->ports[i]);
nfp_eth_read_media(cpp, nsp, &table->ports[i]);
}
kfree(entries); kfree(entries);
...@@ -647,29 +673,3 @@ int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes) ...@@ -647,29 +673,3 @@ int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes)
return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES, return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
lanes, NSP_ETH_CTRL_SET_LANES); lanes, NSP_ETH_CTRL_SET_LANES);
} }
int nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_eth_media_buf *ethm)
{
struct nfp_nsp *nsp;
int ret;
nsp = nfp_nsp_open(cpp);
if (IS_ERR(nsp)) {
nfp_err(cpp, "Failed to access the NSP: %pe\n", nsp);
return PTR_ERR(nsp);
}
if (!nfp_nsp_has_read_media(nsp)) {
nfp_warn(cpp, "Reading media link modes not supported. Please update flash\n");
ret = -EOPNOTSUPP;
goto exit_close_nsp;
}
ret = nfp_nsp_read_media(nsp, ethm, sizeof(*ethm));
if (ret)
nfp_err(cpp, "Reading media link modes failed: %pe\n", ERR_PTR(ret));
exit_close_nsp:
nfp_nsp_close(nsp);
return ret;
}
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