Commit 4540c29a authored by Yu Xiao's avatar Yu Xiao Committed by Jakub Kicinski

nfp: ethtool: support TX/RX pause frame on/off

Add support for ethtool -A tx on/off and rx on/off.
Signed-off-by: default avatarYu Xiao <yu.xiao@corigine.com>
Signed-off-by: default avatarLouis Peens <louis.peens@corigine.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Link: https://lore.kernel.org/r/20231127055116.6668-1-louis.peens@corigine.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a3799729
...@@ -2235,6 +2235,30 @@ static int nfp_net_set_channels(struct net_device *netdev, ...@@ -2235,6 +2235,30 @@ static int nfp_net_set_channels(struct net_device *netdev,
return nfp_net_set_num_rings(nn, total_rx, total_tx); return nfp_net_set_num_rings(nn, total_rx, total_tx);
} }
static int nfp_port_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct nfp_eth_table_port *eth_port;
struct nfp_port *port;
int err;
port = nfp_port_from_netdev(netdev);
eth_port = nfp_port_get_eth_port(port);
if (!eth_port)
return -EOPNOTSUPP;
if (pause->autoneg != AUTONEG_DISABLE)
return -EOPNOTSUPP;
err = nfp_eth_set_pauseparam(port->app->cpp, eth_port->index,
pause->tx_pause, pause->rx_pause);
if (!err)
/* Only refresh if we did something */
nfp_net_refresh_port_table(port);
return err < 0 ? err : 0;
}
static void nfp_port_get_pauseparam(struct net_device *netdev, static void nfp_port_get_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause) struct ethtool_pauseparam *pause)
{ {
...@@ -2246,10 +2270,10 @@ static void nfp_port_get_pauseparam(struct net_device *netdev, ...@@ -2246,10 +2270,10 @@ static void nfp_port_get_pauseparam(struct net_device *netdev,
if (!eth_port) if (!eth_port)
return; return;
/* Currently pause frame support is fixed */ /* Currently pause frame autoneg is fixed */
pause->autoneg = AUTONEG_DISABLE; pause->autoneg = AUTONEG_DISABLE;
pause->rx_pause = 1; pause->rx_pause = eth_port->rx_pause;
pause->tx_pause = 1; pause->tx_pause = eth_port->tx_pause;
} }
static int nfp_net_set_phys_id(struct net_device *netdev, static int nfp_net_set_phys_id(struct net_device *netdev,
...@@ -2475,6 +2499,7 @@ static const struct ethtool_ops nfp_net_ethtool_ops = { ...@@ -2475,6 +2499,7 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
.set_link_ksettings = nfp_net_set_link_ksettings, .set_link_ksettings = nfp_net_set_link_ksettings,
.get_fecparam = nfp_port_get_fecparam, .get_fecparam = nfp_port_get_fecparam,
.set_fecparam = nfp_port_set_fecparam, .set_fecparam = nfp_port_set_fecparam,
.set_pauseparam = nfp_port_set_pauseparam,
.get_pauseparam = nfp_port_get_pauseparam, .get_pauseparam = nfp_port_get_pauseparam,
.set_phys_id = nfp_net_set_phys_id, .set_phys_id = nfp_net_set_phys_id,
}; };
...@@ -2499,6 +2524,7 @@ const struct ethtool_ops nfp_port_ethtool_ops = { ...@@ -2499,6 +2524,7 @@ const struct ethtool_ops nfp_port_ethtool_ops = {
.set_link_ksettings = nfp_net_set_link_ksettings, .set_link_ksettings = nfp_net_set_link_ksettings,
.get_fecparam = nfp_port_get_fecparam, .get_fecparam = nfp_port_get_fecparam,
.set_fecparam = nfp_port_set_fecparam, .set_fecparam = nfp_port_set_fecparam,
.set_pauseparam = nfp_port_set_pauseparam,
.get_pauseparam = nfp_port_get_pauseparam, .get_pauseparam = nfp_port_get_pauseparam,
.set_phys_id = nfp_net_set_phys_id, .set_phys_id = nfp_net_set_phys_id,
}; };
......
...@@ -189,6 +189,8 @@ enum nfp_ethtool_link_mode_list { ...@@ -189,6 +189,8 @@ enum nfp_ethtool_link_mode_list {
* @ports.enabled: is enabled? * @ports.enabled: is enabled?
* @ports.tx_enabled: is TX enabled? * @ports.tx_enabled: is TX enabled?
* @ports.rx_enabled: is RX enabled? * @ports.rx_enabled: is RX enabled?
* @ports.rx_pause: Switch of RX pause frame
* @ports.tx_pause: Switch of Tx pause frame
* @ports.override_changed: is media reconfig pending? * @ports.override_changed: is media reconfig pending?
* *
* @ports.port_type: one of %PORT_* defines for ethtool * @ports.port_type: one of %PORT_* defines for ethtool
...@@ -227,6 +229,8 @@ struct nfp_eth_table { ...@@ -227,6 +229,8 @@ struct nfp_eth_table {
bool tx_enabled; bool tx_enabled;
bool rx_enabled; bool rx_enabled;
bool supp_aneg; bool supp_aneg;
bool rx_pause;
bool tx_pause;
bool override_changed; bool override_changed;
...@@ -255,6 +259,8 @@ int ...@@ -255,6 +259,8 @@ int
nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode); nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode);
int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsigned int idx, bool state); int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsigned int idx, bool state);
int nfp_eth_set_pauseparam(struct nfp_cpp *cpp, unsigned int idx,
unsigned int tx_pause, unsigned int rx_pause);
static inline bool nfp_eth_can_support_fec(struct nfp_eth_table_port *eth_port) static inline bool nfp_eth_can_support_fec(struct nfp_eth_table_port *eth_port)
{ {
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
#define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23) #define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23)
#define NSP_ETH_STATE_FEC GENMASK_ULL(27, 26) #define NSP_ETH_STATE_FEC GENMASK_ULL(27, 26)
#define NSP_ETH_STATE_ACT_FEC GENMASK_ULL(29, 28) #define NSP_ETH_STATE_ACT_FEC GENMASK_ULL(29, 28)
#define NSP_ETH_STATE_TX_PAUSE BIT_ULL(31)
#define NSP_ETH_STATE_RX_PAUSE BIT_ULL(32)
#define NSP_ETH_CTRL_CONFIGURED BIT_ULL(0) #define NSP_ETH_CTRL_CONFIGURED BIT_ULL(0)
#define NSP_ETH_CTRL_ENABLED BIT_ULL(1) #define NSP_ETH_CTRL_ENABLED BIT_ULL(1)
...@@ -52,6 +54,8 @@ ...@@ -52,6 +54,8 @@
#define NSP_ETH_CTRL_SET_ANEG BIT_ULL(6) #define NSP_ETH_CTRL_SET_ANEG BIT_ULL(6)
#define NSP_ETH_CTRL_SET_FEC BIT_ULL(7) #define NSP_ETH_CTRL_SET_FEC BIT_ULL(7)
#define NSP_ETH_CTRL_SET_IDMODE BIT_ULL(8) #define NSP_ETH_CTRL_SET_IDMODE BIT_ULL(8)
#define NSP_ETH_CTRL_SET_TX_PAUSE BIT_ULL(10)
#define NSP_ETH_CTRL_SET_RX_PAUSE BIT_ULL(11)
enum nfp_eth_raw { enum nfp_eth_raw {
NSP_ETH_RAW_PORT = 0, NSP_ETH_RAW_PORT = 0,
...@@ -180,6 +184,15 @@ nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src, ...@@ -180,6 +184,15 @@ nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src,
dst->act_fec = FIELD_GET(NSP_ETH_STATE_ACT_FEC, state); dst->act_fec = FIELD_GET(NSP_ETH_STATE_ACT_FEC, state);
dst->supp_aneg = FIELD_GET(NSP_ETH_PORT_SUPP_ANEG, port); dst->supp_aneg = FIELD_GET(NSP_ETH_PORT_SUPP_ANEG, port);
if (nfp_nsp_get_abi_ver_minor(nsp) < 37) {
dst->tx_pause = true;
dst->rx_pause = true;
return;
}
dst->tx_pause = FIELD_GET(NSP_ETH_STATE_TX_PAUSE, state);
dst->rx_pause = FIELD_GET(NSP_ETH_STATE_RX_PAUSE, state);
} }
static void static void
...@@ -497,7 +510,7 @@ int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed) ...@@ -497,7 +510,7 @@ int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed)
static int static int
nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx, nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx,
const u64 mask, const unsigned int shift, const u64 mask, const unsigned int shift,
unsigned int val, const u64 ctrl_bit) u64 val, const u64 ctrl_bit)
{ {
union eth_table_entry *entries = nfp_nsp_config_entries(nsp); union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
unsigned int idx = nfp_nsp_config_idx(nsp); unsigned int idx = nfp_nsp_config_idx(nsp);
...@@ -629,6 +642,81 @@ nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode) ...@@ -629,6 +642,81 @@ nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode)
return nfp_eth_config_commit_end(nsp); return nfp_eth_config_commit_end(nsp);
} }
/**
* __nfp_eth_set_txpause() - set tx pause control bit
* @nsp: NFP NSP handle returned from nfp_eth_config_start()
* @tx_pause: TX pause switch
*
* Set TX pause switch.
*
* Return: 0 or -ERRNO.
*/
static int __nfp_eth_set_txpause(struct nfp_nsp *nsp, unsigned int tx_pause)
{
return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE, NSP_ETH_STATE_TX_PAUSE,
tx_pause, NSP_ETH_CTRL_SET_TX_PAUSE);
}
/**
* __nfp_eth_set_rxpause() - set rx pause control bit
* @nsp: NFP NSP handle returned from nfp_eth_config_start()
* @rx_pause: RX pause switch
*
* Set RX pause switch.
*
* Return: 0 or -ERRNO.
*/
static int __nfp_eth_set_rxpause(struct nfp_nsp *nsp, unsigned int rx_pause)
{
return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE, NSP_ETH_STATE_RX_PAUSE,
rx_pause, NSP_ETH_CTRL_SET_RX_PAUSE);
}
/**
* nfp_eth_set_pauseparam() - Set TX/RX pause switch.
* @cpp: NFP CPP handle
* @idx: NFP chip-wide port index
* @tx_pause: TX pause switch
* @rx_pause: RX pause switch
*
* Return:
* 0 - configuration successful;
* 1 - no changes were needed;
* -ERRNO - configuration failed.
*/
int
nfp_eth_set_pauseparam(struct nfp_cpp *cpp, unsigned int idx,
unsigned int tx_pause, unsigned int rx_pause)
{
struct nfp_nsp *nsp;
int err;
nsp = nfp_eth_config_start(cpp, idx);
if (IS_ERR(nsp))
return PTR_ERR(nsp);
if (nfp_nsp_get_abi_ver_minor(nsp) < 37) {
nfp_err(nfp_nsp_cpp(nsp),
"set pause parameter operation not supported, please update flash\n");
nfp_eth_config_cleanup_end(nsp);
return -EOPNOTSUPP;
}
err = __nfp_eth_set_txpause(nsp, tx_pause);
if (err) {
nfp_eth_config_cleanup_end(nsp);
return err;
}
err = __nfp_eth_set_rxpause(nsp, rx_pause);
if (err) {
nfp_eth_config_cleanup_end(nsp);
return err;
}
return nfp_eth_config_commit_end(nsp);
}
/** /**
* __nfp_eth_set_speed() - set interface speed/rate * __nfp_eth_set_speed() - set interface speed/rate
* @nsp: NFP NSP handle returned from nfp_eth_config_start() * @nsp: NFP NSP handle returned from nfp_eth_config_start()
......
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