forked from Minki/linux
Merge branch 'mlx5e-next'
Achiad Shochat says: ==================== Driver updates 16-Aug-2015 This patchset contains bug fixes, new RSS and pause parameters ethtool options, and support for RX CHECKSUM_COMPLETE. Patchset was applied and tested over commit adc6310 ("Merge branch 'mv88e6xxx-switchdev-fdb'"). ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9cd3778cd7
@ -42,22 +42,24 @@
|
||||
|
||||
#define MLX5E_MAX_NUM_TC 8
|
||||
|
||||
#define MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE 0x7
|
||||
#define MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE 0x6
|
||||
#define MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE 0xa
|
||||
#define MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE 0xd
|
||||
|
||||
#define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE 0x7
|
||||
#define MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE 0x1
|
||||
#define MLX5E_PARAMS_DEFAULT_LOG_RQ_SIZE 0xa
|
||||
#define MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE 0xd
|
||||
|
||||
#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (16 * 1024)
|
||||
#define MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ (64 * 1024)
|
||||
#define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_USEC 0x10
|
||||
#define MLX5E_PARAMS_DEFAULT_RX_CQ_MODERATION_PKTS 0x20
|
||||
#define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_USEC 0x10
|
||||
#define MLX5E_PARAMS_DEFAULT_TX_CQ_MODERATION_PKTS 0x20
|
||||
#define MLX5E_PARAMS_DEFAULT_MIN_RX_WQES 0x80
|
||||
#define MLX5E_PARAMS_DEFAULT_RX_HASH_LOG_TBL_SZ 0x7
|
||||
|
||||
#define MLX5E_LOG_INDIR_RQT_SIZE 0x7
|
||||
#define MLX5E_INDIR_RQT_SIZE BIT(MLX5E_LOG_INDIR_RQT_SIZE)
|
||||
#define MLX5E_MAX_NUM_CHANNELS (MLX5E_INDIR_RQT_SIZE >> 1)
|
||||
#define MLX5E_TX_CQ_POLL_BUDGET 128
|
||||
#define MLX5E_UPDATE_STATS_INTERVAL 200 /* msecs */
|
||||
#define MLX5E_SQ_BF_BUDGET 16
|
||||
@ -92,6 +94,7 @@ static const char vport_strings[][ETH_GSTRING_LEN] = {
|
||||
"lro_bytes",
|
||||
"rx_csum_good",
|
||||
"rx_csum_none",
|
||||
"rx_csum_sw",
|
||||
"tx_csum_offload",
|
||||
"tx_queue_stopped",
|
||||
"tx_queue_wake",
|
||||
@ -129,13 +132,14 @@ struct mlx5e_vport_stats {
|
||||
u64 lro_bytes;
|
||||
u64 rx_csum_good;
|
||||
u64 rx_csum_none;
|
||||
u64 rx_csum_sw;
|
||||
u64 tx_csum_offload;
|
||||
u64 tx_queue_stopped;
|
||||
u64 tx_queue_wake;
|
||||
u64 tx_queue_dropped;
|
||||
u64 rx_wqe_err;
|
||||
|
||||
#define NUM_VPORT_COUNTERS 31
|
||||
#define NUM_VPORT_COUNTERS 32
|
||||
};
|
||||
|
||||
static const char pport_strings[][ETH_GSTRING_LEN] = {
|
||||
@ -215,6 +219,7 @@ struct mlx5e_pport_stats {
|
||||
static const char rq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
"packets",
|
||||
"csum_none",
|
||||
"csum_sw",
|
||||
"lro_packets",
|
||||
"lro_bytes",
|
||||
"wqe_err"
|
||||
@ -223,10 +228,11 @@ static const char rq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
struct mlx5e_rq_stats {
|
||||
u64 packets;
|
||||
u64 csum_none;
|
||||
u64 csum_sw;
|
||||
u64 lro_packets;
|
||||
u64 lro_bytes;
|
||||
u64 wqe_err;
|
||||
#define NUM_RQ_STATS 5
|
||||
#define NUM_RQ_STATS 6
|
||||
};
|
||||
|
||||
static const char sq_stats_strings[][ETH_GSTRING_LEN] = {
|
||||
@ -268,11 +274,12 @@ struct mlx5e_params {
|
||||
u16 tx_cq_moderation_usec;
|
||||
u16 tx_cq_moderation_pkts;
|
||||
u16 min_rx_wqes;
|
||||
u16 rx_hash_log_tbl_sz;
|
||||
bool lro_en;
|
||||
u32 lro_wqe_sz;
|
||||
u8 rss_hfunc;
|
||||
u16 tx_max_inline;
|
||||
u8 rss_hfunc;
|
||||
u8 toeplitz_hash_key[40];
|
||||
u32 indirection_rqt[MLX5E_INDIR_RQT_SIZE];
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -569,6 +576,8 @@ int mlx5e_vlan_rx_kill_vid(struct net_device *dev, __always_unused __be16 proto,
|
||||
void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv);
|
||||
void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv);
|
||||
|
||||
int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix);
|
||||
|
||||
int mlx5e_open_locked(struct net_device *netdev);
|
||||
int mlx5e_close_locked(struct net_device *netdev);
|
||||
|
||||
|
@ -628,7 +628,7 @@ static int mlx5e_set_settings(struct net_device *netdev,
|
||||
u32 link_modes;
|
||||
u32 speed;
|
||||
u32 eth_proto_cap, eth_proto_admin;
|
||||
u8 port_status;
|
||||
enum mlx5_port_status ps;
|
||||
int err;
|
||||
|
||||
speed = ethtool_cmd_speed(cmd);
|
||||
@ -662,33 +662,42 @@ static int mlx5e_set_settings(struct net_device *netdev,
|
||||
if (link_modes == eth_proto_admin)
|
||||
goto out;
|
||||
|
||||
err = mlx5_set_port_proto(mdev, link_modes, MLX5_PTYS_EN);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: set port eth proto admin failed: %d\n",
|
||||
__func__, err);
|
||||
goto out;
|
||||
}
|
||||
mlx5_query_port_admin_status(mdev, &ps);
|
||||
if (ps == MLX5_PORT_UP)
|
||||
mlx5_set_port_admin_status(mdev, MLX5_PORT_DOWN);
|
||||
mlx5_set_port_proto(mdev, link_modes, MLX5_PTYS_EN);
|
||||
if (ps == MLX5_PORT_UP)
|
||||
mlx5_set_port_admin_status(mdev, MLX5_PORT_UP);
|
||||
|
||||
err = mlx5_query_port_status(mdev, &port_status);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (port_status == MLX5_PORT_DOWN)
|
||||
return 0;
|
||||
|
||||
err = mlx5_set_port_status(mdev, MLX5_PORT_DOWN);
|
||||
if (err)
|
||||
goto out;
|
||||
err = mlx5_set_port_status(mdev, MLX5_PORT_UP);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32 mlx5e_get_rxfh_key_size(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
return sizeof(priv->params.toeplitz_hash_key);
|
||||
}
|
||||
|
||||
static u32 mlx5e_get_rxfh_indir_size(struct net_device *netdev)
|
||||
{
|
||||
return MLX5E_INDIR_RQT_SIZE;
|
||||
}
|
||||
|
||||
static int mlx5e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
||||
if (indir)
|
||||
memcpy(indir, priv->params.indirection_rqt,
|
||||
sizeof(priv->params.indirection_rqt));
|
||||
|
||||
if (key)
|
||||
memcpy(key, priv->params.toeplitz_hash_key,
|
||||
sizeof(priv->params.toeplitz_hash_key));
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = priv->params.rss_hfunc;
|
||||
|
||||
@ -699,28 +708,60 @@ static int mlx5e_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(dev);
|
||||
bool close_open;
|
||||
int err = 0;
|
||||
|
||||
if (hfunc == ETH_RSS_HASH_NO_CHANGE)
|
||||
return 0;
|
||||
|
||||
if ((hfunc != ETH_RSS_HASH_XOR) &&
|
||||
if ((hfunc != ETH_RSS_HASH_NO_CHANGE) &&
|
||||
(hfunc != ETH_RSS_HASH_XOR) &&
|
||||
(hfunc != ETH_RSS_HASH_TOP))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->state_lock);
|
||||
|
||||
priv->params.rss_hfunc = hfunc;
|
||||
if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
|
||||
mlx5e_close_locked(dev);
|
||||
err = mlx5e_open_locked(dev);
|
||||
if (indir) {
|
||||
memcpy(priv->params.indirection_rqt, indir,
|
||||
sizeof(priv->params.indirection_rqt));
|
||||
mlx5e_redirect_rqt(priv, MLX5E_INDIRECTION_RQT);
|
||||
}
|
||||
|
||||
close_open = (key || (hfunc != ETH_RSS_HASH_NO_CHANGE)) &&
|
||||
test_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
if (close_open)
|
||||
mlx5e_close_locked(dev);
|
||||
|
||||
if (key)
|
||||
memcpy(priv->params.toeplitz_hash_key, key,
|
||||
sizeof(priv->params.toeplitz_hash_key));
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE)
|
||||
priv->params.rss_hfunc = hfunc;
|
||||
|
||||
if (close_open)
|
||||
err = mlx5e_open_locked(priv->netdev);
|
||||
|
||||
mutex_unlock(&priv->state_lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_get_rxnfc(struct net_device *netdev,
|
||||
struct ethtool_rxnfc *info, u32 *rule_locs)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int err = 0;
|
||||
|
||||
switch (info->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
info->data = priv->params.num_channels;
|
||||
break;
|
||||
default:
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_get_tunable(struct net_device *dev,
|
||||
const struct ethtool_tunable *tuna,
|
||||
void *data)
|
||||
@ -779,6 +820,42 @@ static int mlx5e_set_tunable(struct net_device *dev,
|
||||
return err;
|
||||
}
|
||||
|
||||
static void mlx5e_get_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
|
||||
err = mlx5_query_port_pause(mdev, &pauseparam->rx_pause,
|
||||
&pauseparam->tx_pause);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5_query_port_pause failed:0x%x\n",
|
||||
__func__, err);
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx5e_set_pauseparam(struct net_device *netdev,
|
||||
struct ethtool_pauseparam *pauseparam)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
|
||||
if (pauseparam->autoneg)
|
||||
return -EINVAL;
|
||||
|
||||
err = mlx5_set_port_pause(mdev,
|
||||
pauseparam->rx_pause ? 1 : 0,
|
||||
pauseparam->tx_pause ? 1 : 0);
|
||||
if (err) {
|
||||
netdev_err(netdev, "%s: mlx5_set_port_pause failed:0x%x\n",
|
||||
__func__, err);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
const struct ethtool_ops mlx5e_ethtool_ops = {
|
||||
.get_drvinfo = mlx5e_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
@ -793,8 +870,13 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
|
||||
.set_coalesce = mlx5e_set_coalesce,
|
||||
.get_settings = mlx5e_get_settings,
|
||||
.set_settings = mlx5e_set_settings,
|
||||
.get_rxfh_key_size = mlx5e_get_rxfh_key_size,
|
||||
.get_rxfh_indir_size = mlx5e_get_rxfh_indir_size,
|
||||
.get_rxfh = mlx5e_get_rxfh,
|
||||
.set_rxfh = mlx5e_set_rxfh,
|
||||
.get_rxnfc = mlx5e_get_rxnfc,
|
||||
.get_tunable = mlx5e_get_tunable,
|
||||
.set_tunable = mlx5e_set_tunable,
|
||||
.get_pauseparam = mlx5e_get_pauseparam,
|
||||
.set_pauseparam = mlx5e_set_pauseparam,
|
||||
};
|
||||
|
@ -149,6 +149,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
|
||||
s->lro_packets = 0;
|
||||
s->lro_bytes = 0;
|
||||
s->rx_csum_none = 0;
|
||||
s->rx_csum_sw = 0;
|
||||
s->rx_wqe_err = 0;
|
||||
for (i = 0; i < priv->params.num_channels; i++) {
|
||||
rq_stats = &priv->channel[i]->rq.stats;
|
||||
@ -156,6 +157,7 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
|
||||
s->lro_packets += rq_stats->lro_packets;
|
||||
s->lro_bytes += rq_stats->lro_bytes;
|
||||
s->rx_csum_none += rq_stats->csum_none;
|
||||
s->rx_csum_sw += rq_stats->csum_sw;
|
||||
s->rx_wqe_err += rq_stats->wqe_err;
|
||||
|
||||
for (j = 0; j < priv->params.num_tc; j++) {
|
||||
@ -241,7 +243,8 @@ void mlx5e_update_stats(struct mlx5e_priv *priv)
|
||||
|
||||
/* Update calculated offload counters */
|
||||
s->tx_csum_offload = s->tx_packets - tx_offload_none;
|
||||
s->rx_csum_good = s->rx_packets - s->rx_csum_none;
|
||||
s->rx_csum_good = s->rx_packets - s->rx_csum_none -
|
||||
s->rx_csum_sw;
|
||||
|
||||
mlx5e_update_pport_counters(priv);
|
||||
free_out:
|
||||
@ -1174,27 +1177,32 @@ static int mlx5e_bits_invert(unsigned long a, int size)
|
||||
return inv;
|
||||
}
|
||||
|
||||
static void mlx5e_fill_rqt_rqns(struct mlx5e_priv *priv, void *rqtc,
|
||||
enum mlx5e_rqt_ix rqt_ix)
|
||||
static void mlx5e_fill_indir_rqt_rqns(struct mlx5e_priv *priv, void *rqtc)
|
||||
{
|
||||
int i;
|
||||
int log_sz;
|
||||
|
||||
switch (rqt_ix) {
|
||||
case MLX5E_INDIRECTION_RQT:
|
||||
log_sz = priv->params.rx_hash_log_tbl_sz;
|
||||
for (i = 0; i < (1 << log_sz); i++) {
|
||||
for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++) {
|
||||
int ix = i;
|
||||
|
||||
if (priv->params.rss_hfunc == ETH_RSS_HASH_XOR)
|
||||
ix = mlx5e_bits_invert(i, log_sz);
|
||||
ix = mlx5e_bits_invert(i, MLX5E_LOG_INDIR_RQT_SIZE);
|
||||
|
||||
ix = priv->params.indirection_rqt[ix];
|
||||
ix = ix % priv->params.num_channels;
|
||||
MLX5_SET(rqtc, rqtc, rq_num[i],
|
||||
test_bit(MLX5E_STATE_OPENED, &priv->state) ?
|
||||
priv->channel[ix]->rq.rqn :
|
||||
priv->drop_rq.rqn);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlx5e_fill_rqt_rqns(struct mlx5e_priv *priv, void *rqtc,
|
||||
enum mlx5e_rqt_ix rqt_ix)
|
||||
{
|
||||
|
||||
switch (rqt_ix) {
|
||||
case MLX5E_INDIRECTION_RQT:
|
||||
mlx5e_fill_indir_rqt_rqns(priv, rqtc);
|
||||
|
||||
break;
|
||||
|
||||
@ -1214,13 +1222,10 @@ static int mlx5e_create_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
u32 *in;
|
||||
void *rqtc;
|
||||
int inlen;
|
||||
int log_sz;
|
||||
int sz;
|
||||
int err;
|
||||
|
||||
log_sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 0 :
|
||||
priv->params.rx_hash_log_tbl_sz;
|
||||
sz = 1 << log_sz;
|
||||
sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 1 : MLX5E_INDIR_RQT_SIZE;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(create_rqt_in) + sizeof(u32) * sz;
|
||||
in = mlx5_vzalloc(inlen);
|
||||
@ -1241,19 +1246,16 @@ static int mlx5e_create_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
int mlx5e_redirect_rqt(struct mlx5e_priv *priv, enum mlx5e_rqt_ix rqt_ix)
|
||||
{
|
||||
struct mlx5_core_dev *mdev = priv->mdev;
|
||||
u32 *in;
|
||||
void *rqtc;
|
||||
int inlen;
|
||||
int log_sz;
|
||||
int sz;
|
||||
int err;
|
||||
|
||||
log_sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 0 :
|
||||
priv->params.rx_hash_log_tbl_sz;
|
||||
sz = 1 << log_sz;
|
||||
sz = (rqt_ix == MLX5E_SINGLE_RQ_RQT) ? 1 : MLX5E_INDIR_RQT_SIZE;
|
||||
|
||||
inlen = MLX5_ST_SZ_BYTES(modify_rqt_in) + sizeof(u32) * sz;
|
||||
in = mlx5_vzalloc(inlen);
|
||||
@ -1301,7 +1303,7 @@ static void mlx5e_build_tir_ctx_lro(void *tirc, struct mlx5e_priv *priv)
|
||||
ROUGH_MAX_L2_L3_HDR_SZ) >> 8);
|
||||
MLX5_SET(tirc, tirc, lro_timeout_period_usecs,
|
||||
MLX5_CAP_ETH(priv->mdev,
|
||||
lro_timer_supported_periods[3]));
|
||||
lro_timer_supported_periods[2]));
|
||||
}
|
||||
|
||||
static int mlx5e_modify_tir_lro(struct mlx5e_priv *priv, int tt)
|
||||
@ -1611,7 +1613,7 @@ static void mlx5e_build_tir_ctx(struct mlx5e_priv *priv, u32 *tirc, int tt)
|
||||
rx_hash_toeplitz_key);
|
||||
|
||||
MLX5_SET(tirc, tirc, rx_hash_symmetric, 1);
|
||||
netdev_rss_key_fill(rss_key, len);
|
||||
memcpy(rss_key, priv->params.toeplitz_hash_key, len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1911,9 +1913,10 @@ u16 mlx5e_get_max_inline_cap(struct mlx5_core_dev *mdev)
|
||||
|
||||
static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
|
||||
struct net_device *netdev,
|
||||
int num_comp_vectors)
|
||||
int num_channels)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
int i;
|
||||
|
||||
priv->params.log_sq_size =
|
||||
MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
|
||||
@ -1930,22 +1933,22 @@ static void mlx5e_build_netdev_priv(struct mlx5_core_dev *mdev,
|
||||
priv->params.tx_max_inline = mlx5e_get_max_inline_cap(mdev);
|
||||
priv->params.min_rx_wqes =
|
||||
MLX5E_PARAMS_DEFAULT_MIN_RX_WQES;
|
||||
priv->params.rx_hash_log_tbl_sz =
|
||||
(order_base_2(num_comp_vectors) >
|
||||
MLX5E_PARAMS_DEFAULT_RX_HASH_LOG_TBL_SZ) ?
|
||||
order_base_2(num_comp_vectors) :
|
||||
MLX5E_PARAMS_DEFAULT_RX_HASH_LOG_TBL_SZ;
|
||||
priv->params.num_tc = 1;
|
||||
priv->params.default_vlan_prio = 0;
|
||||
priv->params.rss_hfunc = ETH_RSS_HASH_XOR;
|
||||
|
||||
priv->params.lro_en = false && !!MLX5_CAP_ETH(priv->mdev, lro_cap);
|
||||
netdev_rss_key_fill(priv->params.toeplitz_hash_key,
|
||||
sizeof(priv->params.toeplitz_hash_key));
|
||||
|
||||
for (i = 0; i < MLX5E_INDIR_RQT_SIZE; i++)
|
||||
priv->params.indirection_rqt[i] = i % num_channels;
|
||||
|
||||
priv->params.lro_wqe_sz =
|
||||
MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
|
||||
|
||||
priv->mdev = mdev;
|
||||
priv->netdev = netdev;
|
||||
priv->params.num_channels = num_comp_vectors;
|
||||
priv->params.num_channels = num_channels;
|
||||
priv->default_vlan_prio = priv->params.default_vlan_prio;
|
||||
|
||||
spin_lock_init(&priv->async_events_spinlock);
|
||||
@ -2034,19 +2037,20 @@ static void *mlx5e_create_netdev(struct mlx5_core_dev *mdev)
|
||||
{
|
||||
struct net_device *netdev;
|
||||
struct mlx5e_priv *priv;
|
||||
int ncv = mdev->priv.eq_table.num_comp_vectors;
|
||||
int nch = min_t(int, mdev->priv.eq_table.num_comp_vectors,
|
||||
MLX5E_MAX_NUM_CHANNELS);
|
||||
int err;
|
||||
|
||||
if (mlx5e_check_required_hca_cap(mdev))
|
||||
return NULL;
|
||||
|
||||
netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv), ncv, ncv);
|
||||
netdev = alloc_etherdev_mqs(sizeof(struct mlx5e_priv), nch, nch);
|
||||
if (!netdev) {
|
||||
mlx5_core_err(mdev, "alloc_etherdev_mqs() failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mlx5e_build_netdev_priv(mdev, netdev, ncv);
|
||||
mlx5e_build_netdev_priv(mdev, netdev, nch);
|
||||
mlx5e_build_netdev(netdev);
|
||||
|
||||
netif_carrier_off(netdev);
|
||||
|
@ -111,10 +111,12 @@ static void mlx5e_lro_update_hdr(struct sk_buff *skb, struct mlx5_cqe64 *cqe)
|
||||
tcp = (struct tcphdr *)(skb->data + ETH_HLEN +
|
||||
sizeof(struct iphdr));
|
||||
ipv6 = NULL;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
|
||||
} else {
|
||||
tcp = (struct tcphdr *)(skb->data + ETH_HLEN +
|
||||
sizeof(struct ipv6hdr));
|
||||
ipv4 = NULL;
|
||||
skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
|
||||
}
|
||||
|
||||
if (get_cqe_lro_tcppsh(cqe))
|
||||
@ -149,6 +151,38 @@ static inline void mlx5e_skb_set_hash(struct mlx5_cqe64 *cqe,
|
||||
skb_set_hash(skb, be32_to_cpu(cqe->rss_hash_result), ht);
|
||||
}
|
||||
|
||||
static inline bool is_first_ethertype_ip(struct sk_buff *skb)
|
||||
{
|
||||
__be16 ethertype = ((struct ethhdr *)skb->data)->h_proto;
|
||||
|
||||
return (ethertype == htons(ETH_P_IP) || ethertype == htons(ETH_P_IPV6));
|
||||
}
|
||||
|
||||
static inline void mlx5e_handle_csum(struct net_device *netdev,
|
||||
struct mlx5_cqe64 *cqe,
|
||||
struct mlx5e_rq *rq,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
if (unlikely(!(netdev->features & NETIF_F_RXCSUM)))
|
||||
goto csum_none;
|
||||
|
||||
if (likely(cqe->hds_ip_ext & CQE_L4_OK)) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
} else if (is_first_ethertype_ip(skb)) {
|
||||
skb->ip_summed = CHECKSUM_COMPLETE;
|
||||
skb->csum = csum_unfold(cqe->check_sum);
|
||||
rq->stats.csum_sw++;
|
||||
} else {
|
||||
goto csum_none;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
csum_none:
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
rq->stats.csum_none++;
|
||||
}
|
||||
|
||||
static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
|
||||
struct mlx5e_rq *rq,
|
||||
struct sk_buff *skb)
|
||||
@ -162,20 +196,12 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
|
||||
lro_num_seg = be32_to_cpu(cqe->srqn) >> 24;
|
||||
if (lro_num_seg > 1) {
|
||||
mlx5e_lro_update_hdr(skb, cqe);
|
||||
skb_shinfo(skb)->gso_size = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
|
||||
skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg);
|
||||
rq->stats.lro_packets++;
|
||||
rq->stats.lro_bytes += cqe_bcnt;
|
||||
}
|
||||
|
||||
if (likely(netdev->features & NETIF_F_RXCSUM) &&
|
||||
(cqe->hds_ip_ext & CQE_L2_OK) &&
|
||||
(cqe->hds_ip_ext & CQE_L3_OK) &&
|
||||
(cqe->hds_ip_ext & CQE_L4_OK)) {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
} else {
|
||||
skb->ip_summed = CHECKSUM_NONE;
|
||||
rq->stats.csum_none++;
|
||||
}
|
||||
mlx5e_handle_csum(netdev, cqe, rq, skb);
|
||||
|
||||
skb->protocol = eth_type_trans(skb, netdev);
|
||||
|
||||
|
@ -216,7 +216,7 @@ int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_set_port_proto);
|
||||
|
||||
int mlx5_set_port_status(struct mlx5_core_dev *dev,
|
||||
int mlx5_set_port_admin_status(struct mlx5_core_dev *dev,
|
||||
enum mlx5_port_status status)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(paos_reg)];
|
||||
@ -224,14 +224,17 @@ int mlx5_set_port_status(struct mlx5_core_dev *dev,
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
|
||||
MLX5_SET(paos_reg, in, local_port, 1);
|
||||
MLX5_SET(paos_reg, in, admin_status, status);
|
||||
MLX5_SET(paos_reg, in, ase, 1);
|
||||
|
||||
return mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_PAOS, 0, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_set_port_admin_status);
|
||||
|
||||
int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
|
||||
int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
|
||||
enum mlx5_port_status *status)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(paos_reg)];
|
||||
u32 out[MLX5_ST_SZ_DW(paos_reg)];
|
||||
@ -239,14 +242,17 @@ int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status)
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
|
||||
MLX5_SET(paos_reg, in, local_port, 1);
|
||||
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_PAOS, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
*status = MLX5_GET(paos_reg, out, oper_status);
|
||||
*status = MLX5_GET(paos_reg, out, admin_status);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_port_admin_status);
|
||||
|
||||
static void mlx5_query_port_mtu(struct mlx5_core_dev *dev, int *admin_mtu,
|
||||
int *max_mtu, int *oper_mtu, u8 port)
|
||||
@ -328,3 +334,45 @@ int mlx5_query_port_vl_hw_cap(struct mlx5_core_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_port_vl_hw_cap);
|
||||
|
||||
int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 rx_pause, u32 tx_pause)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
|
||||
u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
|
||||
int err;
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
MLX5_SET(pfcc_reg, in, local_port, 1);
|
||||
MLX5_SET(pfcc_reg, in, pptx, tx_pause);
|
||||
MLX5_SET(pfcc_reg, in, pprx, rx_pause);
|
||||
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_PFCC, 0, 1);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_set_port_pause);
|
||||
|
||||
int mlx5_query_port_pause(struct mlx5_core_dev *dev,
|
||||
u32 *rx_pause, u32 *tx_pause)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(pfcc_reg)];
|
||||
u32 out[MLX5_ST_SZ_DW(pfcc_reg)];
|
||||
int err;
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
MLX5_SET(pfcc_reg, in, local_port, 1);
|
||||
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_PFCC, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (rx_pause)
|
||||
*rx_pause = MLX5_GET(pfcc_reg, out, pprx);
|
||||
|
||||
if (tx_pause)
|
||||
*tx_pause = MLX5_GET(pfcc_reg, out, pptx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx5_query_port_pause);
|
||||
|
@ -103,6 +103,7 @@ enum {
|
||||
MLX5_REG_PMTU = 0x5003,
|
||||
MLX5_REG_PTYS = 0x5004,
|
||||
MLX5_REG_PAOS = 0x5006,
|
||||
MLX5_REG_PFCC = 0x5007,
|
||||
MLX5_REG_PPCNT = 0x5008,
|
||||
MLX5_REG_PMAOS = 0x5012,
|
||||
MLX5_REG_PUDE = 0x5009,
|
||||
@ -152,8 +153,8 @@ enum mlx5_dev_event {
|
||||
};
|
||||
|
||||
enum mlx5_port_status {
|
||||
MLX5_PORT_UP = 1 << 1,
|
||||
MLX5_PORT_DOWN = 1 << 2,
|
||||
MLX5_PORT_UP = 1,
|
||||
MLX5_PORT_DOWN = 2,
|
||||
};
|
||||
|
||||
struct mlx5_uuar_info {
|
||||
@ -761,9 +762,10 @@ int mlx5_query_port_proto_oper(struct mlx5_core_dev *dev,
|
||||
u8 local_port);
|
||||
int mlx5_set_port_proto(struct mlx5_core_dev *dev, u32 proto_admin,
|
||||
int proto_mask);
|
||||
int mlx5_set_port_status(struct mlx5_core_dev *dev,
|
||||
int mlx5_set_port_admin_status(struct mlx5_core_dev *dev,
|
||||
enum mlx5_port_status status);
|
||||
int mlx5_query_port_status(struct mlx5_core_dev *dev, u8 *status);
|
||||
int mlx5_query_port_admin_status(struct mlx5_core_dev *dev,
|
||||
enum mlx5_port_status *status);
|
||||
|
||||
int mlx5_set_port_mtu(struct mlx5_core_dev *dev, int mtu, u8 port);
|
||||
void mlx5_query_port_max_mtu(struct mlx5_core_dev *dev, int *max_mtu, u8 port);
|
||||
@ -773,6 +775,10 @@ void mlx5_query_port_oper_mtu(struct mlx5_core_dev *dev, int *oper_mtu,
|
||||
int mlx5_query_port_vl_hw_cap(struct mlx5_core_dev *dev,
|
||||
u8 *vl_hw_cap, u8 local_port);
|
||||
|
||||
int mlx5_set_port_pause(struct mlx5_core_dev *dev, u32 rx_pause, u32 tx_pause);
|
||||
int mlx5_query_port_pause(struct mlx5_core_dev *dev,
|
||||
u32 *rx_pause, u32 *tx_pause);
|
||||
|
||||
int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq);
|
||||
void mlx5_debug_eq_remove(struct mlx5_core_dev *dev, struct mlx5_eq *eq);
|
||||
int mlx5_core_eq_query(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
|
||||
|
Loading…
Reference in New Issue
Block a user