Skip to content

Commit

Permalink
Merge branch 'mlx4-XDP-tx-refactor'
Browse files Browse the repository at this point in the history
Tariq Toukan says:

====================
mlx4 XDP TX refactor

This patchset refactors the XDP forwarding case, so that
its dedicated transmit queues are managed in a complete
separation from the other regular ones.

It also adds ethtool counters for XDP cases.

Series generated against net-next commit:
22ca904 genetlink: fix error return code in genl_register_family()

Thanks,
Tariq.

v3:
* Exposed per ring counters.

v2:
* Added ethtool counters.
* Rebased, now patch 2 reverts Brenden's fix, as the bug no longer exists:
  958b3d3 ("net/mlx4_en: fixup xdp tx irq to match rx")
* Updated commit message of patch 2.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 2, 2016
2 parents e4ff952 + 15fca2c commit 55454e9
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 229 deletions.
28 changes: 10 additions & 18 deletions drivers/net/ethernet/mellanox/mlx4/en_cq.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
cq->buf_size = cq->size * mdev->dev->caps.cqe_size;

cq->ring = ring;
cq->is_tx = mode;
cq->type = mode;
cq->vector = mdev->dev->caps.num_comp_vectors;

/* Allocate HW buffers on provided NUMA node.
Expand Down Expand Up @@ -104,7 +104,7 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
*cq->mcq.arm_db = 0;
memset(cq->buf, 0, cq->buf_size);

if (cq->is_tx == RX) {
if (cq->type == RX) {
if (!mlx4_is_eq_vector_valid(mdev->dev, priv->port,
cq->vector)) {
cq->vector = cpumask_first(priv->rx_ring[cq->ring]->affinity_mask);
Expand All @@ -127,25 +127,17 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
/* For TX we use the same irq per
ring we assigned for the RX */
struct mlx4_en_cq *rx_cq;
int xdp_index;

/* The xdp tx irq must align with the rx ring that forwards to
* it, so reindex these from 0. This should only happen when
* tx_ring_num is not a multiple of rx_ring_num.
*/
xdp_index = (priv->xdp_ring_num - priv->tx_ring_num) + cq_idx;
if (xdp_index >= 0)
cq_idx = xdp_index;

cq_idx = cq_idx % priv->rx_ring_num;
rx_cq = priv->rx_cq[cq_idx];
cq->vector = rx_cq->vector;
}

if (!cq->is_tx)
if (cq->type == RX)
cq->size = priv->rx_ring[cq->ring]->actual_size;

if ((cq->is_tx && priv->hwtstamp_config.tx_type) ||
(!cq->is_tx && priv->hwtstamp_config.rx_filter))
if ((cq->type != RX && priv->hwtstamp_config.tx_type) ||
(cq->type == RX && priv->hwtstamp_config.rx_filter))
timestamp_en = 1;

err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt,
Expand All @@ -154,10 +146,10 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
if (err)
goto free_eq;

cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
cq->mcq.comp = cq->type != RX ? mlx4_en_tx_irq : mlx4_en_rx_irq;
cq->mcq.event = mlx4_en_cq_event;

if (cq->is_tx)
if (cq->type != RX)
netif_tx_napi_add(cq->dev, &cq->napi, mlx4_en_poll_tx_cq,
NAPI_POLL_WEIGHT);
else
Expand All @@ -181,7 +173,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq)

mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
if (mlx4_is_eq_vector_valid(mdev->dev, priv->port, cq->vector) &&
cq->is_tx == RX)
cq->type == RX)
mlx4_release_eq(priv->mdev->dev, cq->vector);
cq->vector = 0;
cq->buf_size = 0;
Expand All @@ -193,7 +185,7 @@ void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq)
void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
{
napi_disable(&cq->napi);
if (!cq->is_tx) {
if (cq->type == RX) {
napi_hash_del(&cq->napi);
synchronize_rcu();
}
Expand Down
101 changes: 69 additions & 32 deletions drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,19 @@

static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
{
int i;
int i, t;
int err = 0;

for (i = 0; i < priv->tx_ring_num; i++) {
priv->tx_cq[i]->moder_cnt = priv->tx_frames;
priv->tx_cq[i]->moder_time = priv->tx_usecs;
if (priv->port_up) {
err = mlx4_en_set_cq_moder(priv, priv->tx_cq[i]);
if (err)
return err;
for (t = 0 ; t < MLX4_EN_NUM_TX_TYPES; t++) {
for (i = 0; i < priv->tx_ring_num[t]; i++) {
priv->tx_cq[t][i]->moder_cnt = priv->tx_frames;
priv->tx_cq[t][i]->moder_time = priv->tx_usecs;
if (priv->port_up) {
err = mlx4_en_set_cq_moder(priv,
priv->tx_cq[t][i]);
if (err)
return err;
}
}
}

Expand Down Expand Up @@ -192,6 +195,10 @@ static const char main_strings[][ETH_GSTRING_LEN] = {
"tx_prio_7_packets", "tx_prio_7_bytes",
"tx_novlan_packets", "tx_novlan_bytes",

/* xdp statistics */
"rx_xdp_drop",
"rx_xdp_tx",
"rx_xdp_tx_full",
};

static const char mlx4_en_test_names[][ETH_GSTRING_LEN]= {
Expand Down Expand Up @@ -336,8 +343,8 @@ static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
switch (sset) {
case ETH_SS_STATS:
return bitmap_iterator_count(&it) +
(priv->tx_ring_num * 2) +
(priv->rx_ring_num * 3);
(priv->tx_ring_num[TX] * 2) +
(priv->rx_ring_num * (3 + NUM_XDP_STATS));
case ETH_SS_TEST:
return MLX4_EN_NUM_SELF_TEST - !(priv->mdev->dev->caps.flags
& MLX4_DEV_CAP_FLAG_UC_LOOPBACK) * 2;
Expand Down Expand Up @@ -397,14 +404,21 @@ static void mlx4_en_get_ethtool_stats(struct net_device *dev,
if (bitmap_iterator_test(&it))
data[index++] = ((unsigned long *)&priv->pkstats)[i];

for (i = 0; i < priv->tx_ring_num; i++) {
data[index++] = priv->tx_ring[i]->packets;
data[index++] = priv->tx_ring[i]->bytes;
for (i = 0; i < NUM_XDP_STATS; i++, bitmap_iterator_inc(&it))
if (bitmap_iterator_test(&it))
data[index++] = ((unsigned long *)&priv->xdp_stats)[i];

for (i = 0; i < priv->tx_ring_num[TX]; i++) {
data[index++] = priv->tx_ring[TX][i]->packets;
data[index++] = priv->tx_ring[TX][i]->bytes;
}
for (i = 0; i < priv->rx_ring_num; i++) {
data[index++] = priv->rx_ring[i]->packets;
data[index++] = priv->rx_ring[i]->bytes;
data[index++] = priv->rx_ring[i]->dropped;
data[index++] = priv->rx_ring[i]->xdp_drop;
data[index++] = priv->rx_ring[i]->xdp_tx;
data[index++] = priv->rx_ring[i]->xdp_tx_full;
}
spin_unlock_bh(&priv->stats_lock);

Expand Down Expand Up @@ -467,7 +481,13 @@ static void mlx4_en_get_strings(struct net_device *dev,
strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[strings]);

for (i = 0; i < priv->tx_ring_num; i++) {
for (i = 0; i < NUM_XDP_STATS; i++, strings++,
bitmap_iterator_inc(&it))
if (bitmap_iterator_test(&it))
strcpy(data + (index++) * ETH_GSTRING_LEN,
main_strings[strings]);

for (i = 0; i < priv->tx_ring_num[TX]; i++) {
sprintf(data + (index++) * ETH_GSTRING_LEN,
"tx%d_packets", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
Expand All @@ -480,6 +500,12 @@ static void mlx4_en_get_strings(struct net_device *dev,
"rx%d_bytes", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_dropped", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_xdp_drop", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_xdp_tx", i);
sprintf(data + (index++) * ETH_GSTRING_LEN,
"rx%d_xdp_tx_full", i);
}
break;
case ETH_SS_PRIV_FLAGS:
Expand Down Expand Up @@ -1060,7 +1086,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,

if (rx_size == (priv->port_up ? priv->rx_ring[0]->actual_size :
priv->rx_ring[0]->size) &&
tx_size == priv->tx_ring[0]->size)
tx_size == priv->tx_ring[TX][0]->size)
return 0;

tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
Expand Down Expand Up @@ -1105,7 +1131,7 @@ static void mlx4_en_get_ringparam(struct net_device *dev,
param->tx_max_pending = MLX4_EN_MAX_TX_SIZE;
param->rx_pending = priv->port_up ?
priv->rx_ring[0]->actual_size : priv->rx_ring[0]->size;
param->tx_pending = priv->tx_ring[0]->size;
param->tx_pending = priv->tx_ring[TX][0]->size;
}

static u32 mlx4_en_get_rxfh_indir_size(struct net_device *dev)
Expand Down Expand Up @@ -1710,7 +1736,7 @@ static void mlx4_en_get_channels(struct net_device *dev,
channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;

channel->rx_count = priv->rx_ring_num;
channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
channel->tx_count = priv->tx_ring_num[TX] / MLX4_EN_NUM_UP;
}

static int mlx4_en_set_channels(struct net_device *dev,
Expand All @@ -1721,6 +1747,7 @@ static int mlx4_en_set_channels(struct net_device *dev,
struct mlx4_en_port_profile new_prof;
struct mlx4_en_priv *tmp;
int port_up = 0;
int xdp_count;
int err = 0;

if (channel->other_count || channel->combined_count ||
Expand All @@ -1729,20 +1756,25 @@ static int mlx4_en_set_channels(struct net_device *dev,
!channel->tx_count || !channel->rx_count)
return -EINVAL;

if (channel->tx_count * MLX4_EN_NUM_UP <= priv->xdp_ring_num) {
en_err(priv, "Minimum %d tx channels required with XDP on\n",
priv->xdp_ring_num / MLX4_EN_NUM_UP + 1);
return -EINVAL;
}

tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp)
return -ENOMEM;

mutex_lock(&mdev->state_lock);
xdp_count = priv->tx_ring_num[TX_XDP] ? channel->rx_count : 0;
if (channel->tx_count * MLX4_EN_NUM_UP + xdp_count > MAX_TX_RINGS) {
err = -EINVAL;
en_err(priv,
"Total number of TX and XDP rings (%d) exceeds the maximum supported (%d)\n",
channel->tx_count * MLX4_EN_NUM_UP + xdp_count,
MAX_TX_RINGS);
goto out;
}

memcpy(&new_prof, priv->prof, sizeof(struct mlx4_en_port_profile));
new_prof.num_tx_rings_p_up = channel->tx_count;
new_prof.tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
new_prof.tx_ring_num[TX] = channel->tx_count * MLX4_EN_NUM_UP;
new_prof.tx_ring_num[TX_XDP] = xdp_count;
new_prof.rx_ring_num = channel->rx_count;

err = mlx4_en_try_alloc_resources(priv, tmp, &new_prof);
Expand All @@ -1756,14 +1788,13 @@ static int mlx4_en_set_channels(struct net_device *dev,

mlx4_en_safe_replace_resources(priv, tmp);

netif_set_real_num_tx_queues(dev, priv->tx_ring_num -
priv->xdp_ring_num);
netif_set_real_num_tx_queues(dev, priv->tx_ring_num[TX]);
netif_set_real_num_rx_queues(dev, priv->rx_ring_num);

if (dev->num_tc)
mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);

en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num[TX]);
en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);

if (port_up) {
Expand All @@ -1774,8 +1805,8 @@ static int mlx4_en_set_channels(struct net_device *dev,

err = mlx4_en_moderation_update(priv);
out:
kfree(tmp);
mutex_unlock(&mdev->state_lock);
kfree(tmp);
return err;
}

Expand Down Expand Up @@ -1823,11 +1854,15 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
int ret = 0;

if (bf_enabled_new != bf_enabled_old) {
int t;

if (bf_enabled_new) {
bool bf_supported = true;

for (i = 0; i < priv->tx_ring_num; i++)
bf_supported &= priv->tx_ring[i]->bf_alloced;
for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
for (i = 0; i < priv->tx_ring_num[t]; i++)
bf_supported &=
priv->tx_ring[t][i]->bf_alloced;

if (!bf_supported) {
en_err(priv, "BlueFlame is not supported\n");
Expand All @@ -1839,8 +1874,10 @@ static int mlx4_en_set_priv_flags(struct net_device *dev, u32 flags)
priv->pflags &= ~MLX4_EN_PRIV_FLAGS_BLUEFLAME;
}

for (i = 0; i < priv->tx_ring_num; i++)
priv->tx_ring[i]->bf_enabled = bf_enabled_new;
for (t = 0; t < MLX4_EN_NUM_TX_TYPES; t++)
for (i = 0; i < priv->tx_ring_num[t]; i++)
priv->tx_ring[t][i]->bf_enabled =
bf_enabled_new;

en_info(priv, "BlueFlame %s\n",
bf_enabled_new ? "Enabled" : "Disabled");
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/mellanox/mlx4/en_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
params->prof[i].tx_ppp = pfctx;
params->prof[i].tx_ring_size = MLX4_EN_DEF_TX_RING_SIZE;
params->prof[i].rx_ring_size = MLX4_EN_DEF_RX_RING_SIZE;
params->prof[i].tx_ring_num = params->num_tx_rings_p_up *
params->prof[i].tx_ring_num[TX] = params->num_tx_rings_p_up *
MLX4_EN_NUM_UP;
params->prof[i].rss_rings = 0;
params->prof[i].inline_thold = inline_thold;
Expand Down
Loading

0 comments on commit 55454e9

Please sign in to comment.