Commit 87a5c389 authored by Yevgeny Petrilin's avatar Yevgeny Petrilin Committed by David S. Miller

mlx4_en: Using blue flame support

Doorbell is used according to usage of BlueFlame.
For Blue Flame to work in Ethernet mode QP number should have 0
at bits 6,7.
Allocating range of QPs accordingly.
Signed-off-by: default avatarYevgeny Petrilin <yevgenyp@mellanox.co.il>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9ace5e01
...@@ -931,6 +931,13 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) ...@@ -931,6 +931,13 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
{ {
struct mlx4_en_port_profile *prof = priv->prof; struct mlx4_en_port_profile *prof = priv->prof;
int i; int i;
int base_tx_qpn, err;
err = mlx4_qp_reserve_range(priv->mdev->dev, priv->tx_ring_num, 256, &base_tx_qpn);
if (err) {
en_err(priv, "failed reserving range for TX rings\n");
return err;
}
/* Create tx Rings */ /* Create tx Rings */
for (i = 0; i < priv->tx_ring_num; i++) { for (i = 0; i < priv->tx_ring_num; i++) {
...@@ -938,7 +945,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) ...@@ -938,7 +945,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
prof->tx_ring_size, i, TX)) prof->tx_ring_size, i, TX))
goto err; goto err;
if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], base_tx_qpn + i,
prof->tx_ring_size, TXBB_SIZE)) prof->tx_ring_size, TXBB_SIZE))
goto err; goto err;
} }
...@@ -958,6 +965,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) ...@@ -958,6 +965,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
err: err:
en_err(priv, "Failed to allocate NIC resources\n"); en_err(priv, "Failed to allocate NIC resources\n");
mlx4_qp_release_range(priv->mdev->dev, base_tx_qpn, priv->tx_ring_num);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
enum { enum {
MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */ MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
MAX_BF = 256,
}; };
static int inline_thold __read_mostly = MAX_INLINE; static int inline_thold __read_mostly = MAX_INLINE;
...@@ -52,7 +53,7 @@ module_param_named(inline_thold, inline_thold, int, 0444); ...@@ -52,7 +53,7 @@ module_param_named(inline_thold, inline_thold, int, 0444);
MODULE_PARM_DESC(inline_thold, "threshold for using inline data"); MODULE_PARM_DESC(inline_thold, "threshold for using inline data");
int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring, u32 size, struct mlx4_en_tx_ring *ring, int qpn, u32 size,
u16 stride) u16 stride)
{ {
struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_dev *mdev = priv->mdev;
...@@ -103,23 +104,25 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, ...@@ -103,23 +104,25 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
"buf_size:%d dma:%llx\n", ring, ring->buf, ring->size, "buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map); ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn); ring->qpn = qpn;
if (err) {
en_err(priv, "Failed reserving qp for tx ring.\n");
goto err_map;
}
err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp); err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp);
if (err) { if (err) {
en_err(priv, "Failed allocating qp %d\n", ring->qpn); en_err(priv, "Failed allocating qp %d\n", ring->qpn);
goto err_reserve; goto err_map;
} }
ring->qp.event = mlx4_en_sqp_event; ring->qp.event = mlx4_en_sqp_event;
err = mlx4_bf_alloc(mdev->dev, &ring->bf);
if (err) {
en_dbg(DRV, priv, "working without blueflame (%d)", err);
ring->bf.uar = &mdev->priv_uar;
ring->bf.uar->map = mdev->uar_map;
ring->bf_enabled = false;
} else
ring->bf_enabled = true;
return 0; return 0;
err_reserve:
mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
err_map: err_map:
mlx4_en_unmap_buffer(&ring->wqres.buf); mlx4_en_unmap_buffer(&ring->wqres.buf);
err_hwq_res: err_hwq_res:
...@@ -139,6 +142,8 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, ...@@ -139,6 +142,8 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_dev *mdev = priv->mdev; struct mlx4_en_dev *mdev = priv->mdev;
en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn); en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
if (ring->bf_enabled)
mlx4_bf_free(mdev->dev, &ring->bf);
mlx4_qp_remove(mdev->dev, &ring->qp); mlx4_qp_remove(mdev->dev, &ring->qp);
mlx4_qp_free(mdev->dev, &ring->qp); mlx4_qp_free(mdev->dev, &ring->qp);
mlx4_qp_release_range(mdev->dev, ring->qpn, 1); mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
...@@ -171,6 +176,8 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, ...@@ -171,6 +176,8 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn, mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
ring->cqn, &ring->context); ring->cqn, &ring->context);
if (ring->bf_enabled)
ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context, err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
&ring->qp, &ring->qp_state); &ring->qp, &ring->qp_state);
...@@ -591,6 +598,11 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb) ...@@ -591,6 +598,11 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
return skb_tx_hash(dev, skb); return skb_tx_hash(dev, skb);
} }
static void mlx4_bf_copy(unsigned long *dst, unsigned long *src, unsigned bytecnt)
{
__iowrite64_copy(dst, src, bytecnt / 8);
}
netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_priv *priv = netdev_priv(dev);
...@@ -609,12 +621,13 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -609,12 +621,13 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
int desc_size; int desc_size;
int real_size; int real_size;
dma_addr_t dma; dma_addr_t dma;
u32 index; u32 index, bf_index;
__be32 op_own; __be32 op_own;
u16 vlan_tag = 0; u16 vlan_tag = 0;
int i; int i;
int lso_header_size; int lso_header_size;
void *fragptr; void *fragptr;
bool bounce = false;
if (!priv->port_up) if (!priv->port_up)
goto tx_drop; goto tx_drop;
...@@ -657,13 +670,16 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -657,13 +670,16 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
/* Packet is good - grab an index and transmit it */ /* Packet is good - grab an index and transmit it */
index = ring->prod & ring->size_mask; index = ring->prod & ring->size_mask;
bf_index = ring->prod;
/* See if we have enough space for whole descriptor TXBB for setting /* See if we have enough space for whole descriptor TXBB for setting
* SW ownership on next descriptor; if not, use a bounce buffer. */ * SW ownership on next descriptor; if not, use a bounce buffer. */
if (likely(index + nr_txbb <= ring->size)) if (likely(index + nr_txbb <= ring->size))
tx_desc = ring->buf + index * TXBB_SIZE; tx_desc = ring->buf + index * TXBB_SIZE;
else else {
tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf; tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf;
bounce = true;
}
/* Save skb in tx_info ring */ /* Save skb in tx_info ring */
tx_info = &ring->tx_info[index]; tx_info = &ring->tx_info[index];
...@@ -768,21 +784,37 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -768,21 +784,37 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
ring->prod += nr_txbb; ring->prod += nr_txbb;
/* If we used a bounce buffer then copy descriptor back into place */ /* If we used a bounce buffer then copy descriptor back into place */
if (tx_desc == (struct mlx4_en_tx_desc *) ring->bounce_buf) if (bounce)
tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size); tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
/* Run destructor before passing skb to HW */ /* Run destructor before passing skb to HW */
if (likely(!skb_shared(skb))) if (likely(!skb_shared(skb)))
skb_orphan(skb); skb_orphan(skb);
/* Ensure new descirptor hits memory if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
* before setting ownership of this descriptor to HW */ *(u32 *) (&tx_desc->ctrl.vlan_tag) |= ring->doorbell_qpn;
wmb(); op_own |= htonl((bf_index & 0xffff) << 8);
tx_desc->ctrl.owner_opcode = op_own; /* Ensure new descirptor hits memory
* before setting ownership of this descriptor to HW */
wmb();
tx_desc->ctrl.owner_opcode = op_own;
/* Ring doorbell! */ wmb();
wmb();
writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL); mlx4_bf_copy(ring->bf.reg + ring->bf.offset, (unsigned long *) &tx_desc->ctrl,
desc_size);
wmb();
ring->bf.offset ^= ring->bf.buf_size;
} else {
/* Ensure new descirptor hits memory
* before setting ownership of this descriptor to HW */
wmb();
tx_desc->ctrl.owner_opcode = op_own;
wmb();
writel(ring->doorbell_qpn, ring->bf.uar->map + MLX4_SEND_DOORBELL);
}
/* Poll CQ here */ /* Poll CQ here */
mlx4_en_xmit_poll(priv, tx_ind); mlx4_en_xmit_poll(priv, tx_ind);
......
...@@ -248,6 +248,8 @@ struct mlx4_en_tx_ring { ...@@ -248,6 +248,8 @@ struct mlx4_en_tx_ring {
unsigned long bytes; unsigned long bytes;
unsigned long packets; unsigned long packets;
spinlock_t comp_lock; spinlock_t comp_lock;
struct mlx4_bf bf;
bool bf_enabled;
}; };
struct mlx4_en_rx_desc { struct mlx4_en_rx_desc {
...@@ -518,7 +520,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb); ...@@ -518,7 +520,7 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb);
netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev);
int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring, int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring,
u32 size, u16 stride); int qpn, u32 size, u16 stride);
void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring); void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring);
int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv, int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
struct mlx4_en_tx_ring *ring, struct mlx4_en_tx_ring *ring,
......
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