Convert the mlxen driver to use the BUSDMA(9) APIs instead of
vtophys() when loading mbufs for transmission and reception. While at it all pointer arithmetic and cast qualifier issues were fixed, mostly related to transmission and reception. MFC after: 1 week Sponsored by: Mellanox Technologies Differential Revision: https://reviews.freebsd.org/D4284
This commit is contained in:
parent
a7d4c4c102
commit
3d23c0a436
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=291699
@ -11,5 +11,3 @@ CFLAGS+= -I${.CURDIR}/../../ofed/include
|
||||
CFLAGS+= -I${.CURDIR}/../../compat/linuxkpi/common/include
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
||||
CFLAGS+= -Wno-cast-qual -Wno-pointer-arith
|
||||
|
@ -1247,7 +1247,6 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
PAGE_SIZE);
|
||||
priv->rx_alloc_order = get_order(priv->rx_alloc_size);
|
||||
priv->rx_buf_size = roundup_pow_of_two(priv->rx_mb_size);
|
||||
priv->log_rx_info = ROUNDUP_LOG2(sizeof(struct mlx4_en_rx_buf));
|
||||
en_dbg(DRV, priv, "Rx buf size:%d\n", priv->rx_mb_size);
|
||||
|
||||
/* Configure rx cq's and rings */
|
||||
@ -2091,8 +2090,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||
priv->port = port;
|
||||
priv->port_up = false;
|
||||
priv->flags = prof->flags;
|
||||
priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
|
||||
MLX4_WQE_CTRL_SOLICITED);
|
||||
|
||||
priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
|
||||
priv->tx_ring_num = prof->tx_ring_num;
|
||||
@ -2108,7 +2105,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
priv->rx_ring_num = prof->rx_ring_num;
|
||||
priv->cqe_factor = (mdev->dev->caps.cqe_size == 64) ? 1 : 0;
|
||||
priv->mac_index = -1;
|
||||
|
@ -54,106 +54,135 @@ static void mlx4_en_init_rx_desc(struct mlx4_en_priv *priv,
|
||||
int possible_frags;
|
||||
int i;
|
||||
|
||||
|
||||
/* Set size and memtype fields */
|
||||
for (i = 0; i < priv->num_frags; i++) {
|
||||
rx_desc->data[i].byte_count =
|
||||
cpu_to_be32(priv->frag_info[i].frag_size);
|
||||
rx_desc->data[i].lkey = cpu_to_be32(priv->mdev->mr.key);
|
||||
}
|
||||
rx_desc->data[0].byte_count = cpu_to_be32(priv->rx_mb_size);
|
||||
rx_desc->data[0].lkey = cpu_to_be32(priv->mdev->mr.key);
|
||||
|
||||
/* If the number of used fragments does not fill up the ring stride,
|
||||
* * remaining (unused) fragments must be padded with null address/size
|
||||
* * and a special memory key */
|
||||
/*
|
||||
* If the number of used fragments does not fill up the ring
|
||||
* stride, remaining (unused) fragments must be padded with
|
||||
* null address/size and a special memory key:
|
||||
*/
|
||||
possible_frags = (ring->stride - sizeof(struct mlx4_en_rx_desc)) / DS_SIZE;
|
||||
for (i = priv->num_frags; i < possible_frags; i++) {
|
||||
for (i = 1; i < possible_frags; i++) {
|
||||
rx_desc->data[i].byte_count = 0;
|
||||
rx_desc->data[i].lkey = cpu_to_be32(MLX4_EN_MEMTYPE_PAD);
|
||||
rx_desc->data[i].addr = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int mlx4_en_alloc_buf(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_desc *rx_desc,
|
||||
struct mbuf **mb_list,
|
||||
int i)
|
||||
static int
|
||||
mlx4_en_alloc_buf(struct mlx4_en_rx_ring *ring,
|
||||
__be64 *pdma, struct mlx4_en_rx_mbuf *mb_list)
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct mlx4_en_frag_info *frag_info = &priv->frag_info[i];
|
||||
bus_dma_segment_t segs[1];
|
||||
bus_dmamap_t map;
|
||||
struct mbuf *mb;
|
||||
dma_addr_t dma;
|
||||
int nsegs;
|
||||
int err;
|
||||
|
||||
if (i == 0)
|
||||
mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, frag_info->frag_size);
|
||||
else
|
||||
mb = m_getjcl(M_NOWAIT, MT_DATA, 0, frag_info->frag_size);
|
||||
if (mb == NULL) {
|
||||
priv->port_stats.rx_alloc_failed++;
|
||||
return -ENOMEM;
|
||||
/* try to allocate a new spare mbuf */
|
||||
if (unlikely(ring->spare.mbuf == NULL)) {
|
||||
mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, ring->rx_mb_size);
|
||||
if (unlikely(mb == NULL))
|
||||
return (-ENOMEM);
|
||||
/* setup correct length */
|
||||
mb->m_len = ring->rx_mb_size;
|
||||
|
||||
/* load spare mbuf into BUSDMA */
|
||||
err = -bus_dmamap_load_mbuf_sg(ring->dma_tag, ring->spare.dma_map,
|
||||
mb, segs, &nsegs, BUS_DMA_NOWAIT);
|
||||
if (unlikely(err != 0)) {
|
||||
m_freem(mb);
|
||||
return (err);
|
||||
}
|
||||
KASSERT(nsegs == 1,
|
||||
("Number of segments is expected to be one"));
|
||||
|
||||
/* store spare info */
|
||||
ring->spare.mbuf = mb;
|
||||
ring->spare.paddr_be = cpu_to_be64(segs[0].ds_addr);
|
||||
|
||||
bus_dmamap_sync(ring->dma_tag, ring->spare.dma_map,
|
||||
BUS_DMASYNC_PREREAD);
|
||||
}
|
||||
dma = pci_map_single(mdev->pdev, mb->m_data, frag_info->frag_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
rx_desc->data[i].addr = cpu_to_be64(dma);
|
||||
mb_list[i] = mb;
|
||||
return 0;
|
||||
|
||||
/* synchronize and unload the current mbuf, if any */
|
||||
if (likely(mb_list->mbuf != NULL)) {
|
||||
bus_dmamap_sync(ring->dma_tag, mb_list->dma_map,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(ring->dma_tag, mb_list->dma_map);
|
||||
}
|
||||
|
||||
mb = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, ring->rx_mb_size);
|
||||
if (unlikely(mb == NULL))
|
||||
goto use_spare;
|
||||
|
||||
/* setup correct length */
|
||||
mb->m_len = ring->rx_mb_size;
|
||||
|
||||
err = -bus_dmamap_load_mbuf_sg(ring->dma_tag, mb_list->dma_map,
|
||||
mb, segs, &nsegs, BUS_DMA_NOWAIT);
|
||||
if (unlikely(err != 0)) {
|
||||
m_freem(mb);
|
||||
goto use_spare;
|
||||
}
|
||||
KASSERT(nsegs == 1, ("Number of segments is expected to be one"));
|
||||
|
||||
*pdma = cpu_to_be64(segs[0].ds_addr);
|
||||
mb_list->mbuf = mb;
|
||||
|
||||
bus_dmamap_sync(ring->dma_tag, mb_list->dma_map, BUS_DMASYNC_PREREAD);
|
||||
return (0);
|
||||
|
||||
use_spare:
|
||||
/* swap DMA maps */
|
||||
map = mb_list->dma_map;
|
||||
mb_list->dma_map = ring->spare.dma_map;
|
||||
ring->spare.dma_map = map;
|
||||
|
||||
/* swap MBUFs */
|
||||
mb_list->mbuf = ring->spare.mbuf;
|
||||
ring->spare.mbuf = NULL;
|
||||
|
||||
/* store physical address */
|
||||
*pdma = ring->spare.paddr_be;
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
static int mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring *ring, int index)
|
||||
static void
|
||||
mlx4_en_free_buf(struct mlx4_en_rx_ring *ring, struct mlx4_en_rx_mbuf *mb_list)
|
||||
{
|
||||
struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
|
||||
(ring->buf + (index * ring->stride));
|
||||
struct mbuf **mb_list = ring->rx_info + (index << priv->log_rx_info);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->num_frags; i++)
|
||||
if (mlx4_en_alloc_buf(priv, rx_desc, mb_list, i))
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
while (i--)
|
||||
m_free(mb_list[i]);
|
||||
return -ENOMEM;
|
||||
bus_dmamap_t map = mb_list->dma_map;
|
||||
bus_dmamap_sync(ring->dma_tag, map, BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(ring->dma_tag, map);
|
||||
m_freem(mb_list->mbuf);
|
||||
mb_list->mbuf = NULL; /* safety clearing */
|
||||
}
|
||||
|
||||
static inline void mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
|
||||
static int
|
||||
mlx4_en_prepare_rx_desc(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring *ring, int index)
|
||||
{
|
||||
struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
|
||||
(ring->buf + (index * ring->stride));
|
||||
struct mlx4_en_rx_mbuf *mb_list = ring->mbuf + index;
|
||||
|
||||
mb_list->mbuf = NULL;
|
||||
|
||||
if (mlx4_en_alloc_buf(ring, &rx_desc->data[0].addr, mb_list)) {
|
||||
priv->port_stats.rx_alloc_failed++;
|
||||
return (-ENOMEM);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
mlx4_en_update_rx_prod_db(struct mlx4_en_rx_ring *ring)
|
||||
{
|
||||
*ring->wqres.db.db = cpu_to_be32(ring->prod & 0xffff);
|
||||
}
|
||||
|
||||
static void mlx4_en_free_rx_desc(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring *ring,
|
||||
int index)
|
||||
{
|
||||
struct mlx4_en_frag_info *frag_info;
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct mbuf **mb_list;
|
||||
struct mlx4_en_rx_desc *rx_desc = (struct mlx4_en_rx_desc *)
|
||||
(ring->buf + (index << ring->log_stride));
|
||||
dma_addr_t dma;
|
||||
int nr;
|
||||
|
||||
mb_list = ring->rx_info + (index << priv->log_rx_info);
|
||||
for (nr = 0; nr < priv->num_frags; nr++) {
|
||||
en_dbg(DRV, priv, "Freeing fragment:%d\n", nr);
|
||||
frag_info = &priv->frag_info[nr];
|
||||
dma = be64_to_cpu(rx_desc->data[nr].addr);
|
||||
|
||||
#if BITS_PER_LONG == 64
|
||||
en_dbg(DRV, priv, "Unmaping buffer at dma:0x%lx\n", (u64) dma);
|
||||
#elif BITS_PER_LONG == 32
|
||||
en_dbg(DRV, priv, "Unmaping buffer at dma:0x%llx\n", (u64) dma);
|
||||
#endif
|
||||
pci_unmap_single(mdev->pdev, dma, frag_info->frag_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
m_free(mb_list[nr]);
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
|
||||
{
|
||||
struct mlx4_en_rx_ring *ring;
|
||||
@ -194,7 +223,8 @@ static int mlx4_en_fill_rx_buffers(struct mlx4_en_priv *priv)
|
||||
while (ring->actual_size > new_size) {
|
||||
ring->actual_size--;
|
||||
ring->prod--;
|
||||
mlx4_en_free_rx_desc(priv, ring, ring->actual_size);
|
||||
mlx4_en_free_buf(ring,
|
||||
ring->mbuf + ring->actual_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,100 +244,106 @@ static void mlx4_en_free_rx_buf(struct mlx4_en_priv *priv,
|
||||
while (ring->cons != ring->prod) {
|
||||
index = ring->cons & ring->size_mask;
|
||||
en_dbg(DRV, priv, "Processing descriptor:%d\n", index);
|
||||
mlx4_en_free_rx_desc(priv, ring, index);
|
||||
mlx4_en_free_buf(ring, ring->mbuf + index);
|
||||
++ring->cons;
|
||||
}
|
||||
}
|
||||
|
||||
#if MLX4_EN_MAX_RX_FRAGS == 3
|
||||
static int frag_sizes[] = {
|
||||
FRAG_SZ0,
|
||||
FRAG_SZ1,
|
||||
FRAG_SZ2,
|
||||
};
|
||||
#elif MLX4_EN_MAX_RX_FRAGS == 2
|
||||
static int frag_sizes[] = {
|
||||
FRAG_SZ0,
|
||||
FRAG_SZ1,
|
||||
};
|
||||
#else
|
||||
#error "Unknown MAX_RX_FRAGS"
|
||||
#endif
|
||||
|
||||
void mlx4_en_calc_rx_buf(struct net_device *dev)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
int eff_mtu = dev->if_mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN;
|
||||
int buf_size = 0;
|
||||
int i, frag;
|
||||
|
||||
for (i = 0, frag = 0; buf_size < eff_mtu; frag++, i++) {
|
||||
/*
|
||||
* Allocate small to large but only as much as is needed for
|
||||
* the tail.
|
||||
*/
|
||||
while (i > 0 && eff_mtu - buf_size <= frag_sizes[i - 1])
|
||||
i--;
|
||||
priv->frag_info[frag].frag_size = frag_sizes[i];
|
||||
priv->frag_info[frag].frag_prefix_size = buf_size;
|
||||
buf_size += priv->frag_info[frag].frag_size;
|
||||
}
|
||||
if (eff_mtu > MJUM16BYTES) {
|
||||
en_err(priv, "MTU(%d) is too big\n", dev->if_mtu);
|
||||
eff_mtu = MJUM16BYTES;
|
||||
} else if (eff_mtu > MJUM9BYTES) {
|
||||
eff_mtu = MJUM16BYTES;
|
||||
} else if (eff_mtu > MJUMPAGESIZE) {
|
||||
eff_mtu = MJUM9BYTES;
|
||||
} else if (eff_mtu > MCLBYTES) {
|
||||
eff_mtu = MJUMPAGESIZE;
|
||||
} else {
|
||||
eff_mtu = MCLBYTES;
|
||||
}
|
||||
|
||||
priv->num_frags = frag;
|
||||
priv->rx_mb_size = eff_mtu;
|
||||
priv->log_rx_info =
|
||||
ROUNDUP_LOG2(priv->num_frags * sizeof(struct mbuf *));
|
||||
|
||||
en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d "
|
||||
"num_frags:%d):\n", eff_mtu, priv->num_frags);
|
||||
for (i = 0; i < priv->num_frags; i++) {
|
||||
en_dbg(DRV, priv, " frag:%d - size:%d prefix:%d\n", i,
|
||||
priv->frag_info[i].frag_size,
|
||||
priv->frag_info[i].frag_prefix_size);
|
||||
}
|
||||
en_dbg(DRV, priv, "Effective RX MTU: %d bytes\n", eff_mtu);
|
||||
}
|
||||
|
||||
|
||||
int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring **pring,
|
||||
u32 size, int node)
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct mlx4_en_rx_ring *ring;
|
||||
int err = -ENOMEM;
|
||||
int err;
|
||||
int tmp;
|
||||
uint32_t x;
|
||||
|
||||
ring = kzalloc(sizeof(struct mlx4_en_rx_ring), GFP_KERNEL);
|
||||
if (!ring) {
|
||||
en_err(priv, "Failed to allocate RX ring structure\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/* Create DMA descriptor TAG */
|
||||
if ((err = -bus_dma_tag_create(
|
||||
bus_get_dma_tag(mdev->pdev->dev.bsddev),
|
||||
1, /* any alignment */
|
||||
0, /* no boundary */
|
||||
BUS_SPACE_MAXADDR, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
MJUM16BYTES, /* maxsize */
|
||||
1, /* nsegments */
|
||||
MJUM16BYTES, /* maxsegsize */
|
||||
0, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockfuncarg */
|
||||
&ring->dma_tag))) {
|
||||
en_err(priv, "Failed to create DMA tag\n");
|
||||
goto err_ring;
|
||||
}
|
||||
|
||||
ring->prod = 0;
|
||||
ring->cons = 0;
|
||||
ring->size = size;
|
||||
ring->size_mask = size - 1;
|
||||
ring->stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
|
||||
DS_SIZE * MLX4_EN_MAX_RX_FRAGS);
|
||||
ring->stride = roundup_pow_of_two(
|
||||
sizeof(struct mlx4_en_rx_desc) + DS_SIZE);
|
||||
ring->log_stride = ffs(ring->stride) - 1;
|
||||
ring->buf_size = ring->size * ring->stride + TXBB_SIZE;
|
||||
|
||||
tmp = size * roundup_pow_of_two(MLX4_EN_MAX_RX_FRAGS *
|
||||
sizeof(struct mbuf *));
|
||||
tmp = size * sizeof(struct mlx4_en_rx_mbuf);
|
||||
|
||||
ring->rx_info = kmalloc(tmp, GFP_KERNEL);
|
||||
if (!ring->rx_info) {
|
||||
ring->mbuf = kzalloc(tmp, GFP_KERNEL);
|
||||
if (ring->mbuf == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto err_ring;
|
||||
goto err_dma_tag;
|
||||
}
|
||||
|
||||
en_dbg(DRV, priv, "Allocated rx_info ring at addr:%p size:%d\n",
|
||||
ring->rx_info, tmp);
|
||||
err = -bus_dmamap_create(ring->dma_tag, 0, &ring->spare.dma_map);
|
||||
if (err != 0)
|
||||
goto err_info;
|
||||
|
||||
for (x = 0; x != size; x++) {
|
||||
err = -bus_dmamap_create(ring->dma_tag, 0,
|
||||
&ring->mbuf[x].dma_map);
|
||||
if (err != 0) {
|
||||
while (x--)
|
||||
bus_dmamap_destroy(ring->dma_tag,
|
||||
ring->mbuf[x].dma_map);
|
||||
goto err_info;
|
||||
}
|
||||
}
|
||||
en_dbg(DRV, priv, "Allocated MBUF ring at addr:%p size:%d\n",
|
||||
ring->mbuf, tmp);
|
||||
|
||||
err = mlx4_alloc_hwq_res(mdev->dev, &ring->wqres,
|
||||
ring->buf_size, 2 * PAGE_SIZE);
|
||||
if (err)
|
||||
goto err_info;
|
||||
goto err_dma_map;
|
||||
|
||||
err = mlx4_en_map_buffer(&ring->wqres.buf);
|
||||
if (err) {
|
||||
@ -320,23 +356,29 @@ int mlx4_en_create_rx_ring(struct mlx4_en_priv *priv,
|
||||
|
||||
err_hwq:
|
||||
mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
|
||||
err_dma_map:
|
||||
for (x = 0; x != size; x++) {
|
||||
bus_dmamap_destroy(ring->dma_tag,
|
||||
ring->mbuf[x].dma_map);
|
||||
}
|
||||
bus_dmamap_destroy(ring->dma_tag, ring->spare.dma_map);
|
||||
err_info:
|
||||
vfree(ring->rx_info);
|
||||
vfree(ring->mbuf);
|
||||
err_dma_tag:
|
||||
bus_dma_tag_destroy(ring->dma_tag);
|
||||
err_ring:
|
||||
kfree(ring);
|
||||
|
||||
return err;
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
|
||||
{
|
||||
struct mlx4_en_rx_ring *ring;
|
||||
int i;
|
||||
int ring_ind;
|
||||
int err;
|
||||
int stride = roundup_pow_of_two(sizeof(struct mlx4_en_rx_desc) +
|
||||
DS_SIZE * priv->num_frags);
|
||||
int stride = roundup_pow_of_two(
|
||||
sizeof(struct mlx4_en_rx_desc) + DS_SIZE);
|
||||
|
||||
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
|
||||
ring = priv->rx_ring[ring_ind];
|
||||
@ -412,10 +454,22 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct mlx4_en_rx_ring *ring = *pring;
|
||||
uint32_t x;
|
||||
|
||||
mlx4_en_unmap_buffer(&ring->wqres.buf);
|
||||
mlx4_free_hwq_res(mdev->dev, &ring->wqres, size * stride + TXBB_SIZE);
|
||||
vfree(ring->rx_info);
|
||||
for (x = 0; x != size; x++)
|
||||
bus_dmamap_destroy(ring->dma_tag, ring->mbuf[x].dma_map);
|
||||
/* free spare mbuf, if any */
|
||||
if (ring->spare.mbuf != NULL) {
|
||||
bus_dmamap_sync(ring->dma_tag, ring->spare.dma_map,
|
||||
BUS_DMASYNC_POSTREAD);
|
||||
bus_dmamap_unload(ring->dma_tag, ring->spare.dma_map);
|
||||
m_freem(ring->spare.mbuf);
|
||||
}
|
||||
bus_dmamap_destroy(ring->dma_tag, ring->spare.dma_map);
|
||||
vfree(ring->mbuf);
|
||||
bus_dma_tag_destroy(ring->dma_tag);
|
||||
kfree(ring);
|
||||
*pring = NULL;
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
@ -423,7 +477,6 @@ void mlx4_en_destroy_rx_ring(struct mlx4_en_priv *priv,
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void mlx4_en_deactivate_rx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_ring *ring)
|
||||
{
|
||||
@ -472,69 +525,27 @@ static inline int invalid_cqe(struct mlx4_en_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Unmap a completed descriptor and free unused pages */
|
||||
static int mlx4_en_complete_rx_desc(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_desc *rx_desc,
|
||||
struct mbuf **mb_list,
|
||||
int length)
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct mlx4_en_frag_info *frag_info;
|
||||
dma_addr_t dma;
|
||||
struct mbuf *mb;
|
||||
int nr;
|
||||
|
||||
mb = mb_list[0];
|
||||
mb->m_pkthdr.len = length;
|
||||
/* Collect used fragments while replacing them in the HW descirptors */
|
||||
for (nr = 0; nr < priv->num_frags; nr++) {
|
||||
frag_info = &priv->frag_info[nr];
|
||||
if (length <= frag_info->frag_prefix_size)
|
||||
break;
|
||||
if (nr)
|
||||
mb->m_next = mb_list[nr];
|
||||
mb = mb_list[nr];
|
||||
mb->m_len = frag_info->frag_size;
|
||||
dma = be64_to_cpu(rx_desc->data[nr].addr);
|
||||
|
||||
/* Allocate a replacement page */
|
||||
if (mlx4_en_alloc_buf(priv, rx_desc, mb_list, nr))
|
||||
goto fail;
|
||||
|
||||
/* Unmap buffer */
|
||||
pci_unmap_single(mdev->pdev, dma, frag_info->frag_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
}
|
||||
/* Adjust size of last fragment to match actual length */
|
||||
mb->m_len = length - priv->frag_info[nr - 1].frag_prefix_size;
|
||||
mb->m_next = NULL;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
/* Drop all accumulated fragments (which have already been replaced in
|
||||
* the descriptor) of this packet; remaining fragments are reused... */
|
||||
while (nr > 0) {
|
||||
nr--;
|
||||
m_free(mb_list[nr]);
|
||||
}
|
||||
return -ENOMEM;
|
||||
|
||||
}
|
||||
|
||||
static struct mbuf *mlx4_en_rx_mb(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_rx_desc *rx_desc,
|
||||
struct mbuf **mb_list,
|
||||
unsigned int length)
|
||||
static struct mbuf *
|
||||
mlx4_en_rx_mb(struct mlx4_en_priv *priv, struct mlx4_en_rx_ring *ring,
|
||||
struct mlx4_en_rx_desc *rx_desc, struct mlx4_en_rx_mbuf *mb_list,
|
||||
int length)
|
||||
{
|
||||
struct mbuf *mb;
|
||||
|
||||
mb = mb_list[0];
|
||||
/* Move relevant fragments to mb */
|
||||
if (unlikely(mlx4_en_complete_rx_desc(priv, rx_desc, mb_list, length)))
|
||||
return NULL;
|
||||
/* get mbuf */
|
||||
mb = mb_list->mbuf;
|
||||
|
||||
return mb;
|
||||
/* collect used fragment while atomically replacing it */
|
||||
if (mlx4_en_alloc_buf(ring, &rx_desc->data[0].addr, mb_list))
|
||||
return (NULL);
|
||||
|
||||
/* range check hardware computed value */
|
||||
if (unlikely(length > mb->m_len))
|
||||
length = mb->m_len;
|
||||
|
||||
/* update total packet length in packet header */
|
||||
mb->m_len = mb->m_pkthdr.len = length;
|
||||
return (mb);
|
||||
}
|
||||
|
||||
/* For cpu arch with cache line of 64B the performance is better when cqe size==64B
|
||||
@ -548,7 +559,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
struct mlx4_cqe *cqe;
|
||||
struct mlx4_en_rx_ring *ring = priv->rx_ring[cq->ring];
|
||||
struct mbuf **mb_list;
|
||||
struct mlx4_en_rx_mbuf *mb_list;
|
||||
struct mlx4_en_rx_desc *rx_desc;
|
||||
struct mbuf *mb;
|
||||
struct mlx4_cq *mcq = &cq->mcq;
|
||||
@ -576,7 +587,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
|
||||
/* Process all completed CQEs */
|
||||
while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
|
||||
cons_index & size)) {
|
||||
mb_list = ring->rx_info + (index << priv->log_rx_info);
|
||||
mb_list = ring->mbuf + index;
|
||||
rx_desc = (struct mlx4_en_rx_desc *)
|
||||
(ring->buf + (index << ring->log_stride));
|
||||
|
||||
@ -593,8 +604,9 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
|
||||
*/
|
||||
length = be32_to_cpu(cqe->byte_cnt);
|
||||
length -= ring->fcs_del;
|
||||
mb = mlx4_en_rx_mb(priv, rx_desc, mb_list, length);
|
||||
if (!mb) {
|
||||
|
||||
mb = mlx4_en_rx_mb(priv, ring, rx_desc, mb_list, length);
|
||||
if (unlikely(!mb)) {
|
||||
ring->errors++;
|
||||
goto next;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -93,10 +93,6 @@
|
||||
#define VLAN_MIN_VALUE 1
|
||||
#define VLAN_MAX_VALUE 4094
|
||||
|
||||
/* Typical TSO descriptor with 16 gather entries is 352 bytes... */
|
||||
#define MAX_DESC_SIZE 512
|
||||
#define MAX_DESC_TXBBS (MAX_DESC_SIZE / TXBB_SIZE)
|
||||
|
||||
/*
|
||||
* OS related constants and tunables
|
||||
*/
|
||||
@ -111,26 +107,6 @@ enum mlx4_en_alloc_type {
|
||||
MLX4_EN_ALLOC_REPLACEMENT = 1,
|
||||
};
|
||||
|
||||
/* Receive fragment sizes; we use at most 3 fragments (for 9600 byte MTU
|
||||
* and 4K allocations) */
|
||||
#if MJUMPAGESIZE == 4096
|
||||
enum {
|
||||
FRAG_SZ0 = MCLBYTES,
|
||||
FRAG_SZ1 = MJUMPAGESIZE,
|
||||
FRAG_SZ2 = MJUMPAGESIZE,
|
||||
};
|
||||
#define MLX4_EN_MAX_RX_FRAGS 3
|
||||
#elif MJUMPAGESIZE == 8192
|
||||
enum {
|
||||
FRAG_SZ0 = MCLBYTES,
|
||||
FRAG_SZ1 = MJUMPAGESIZE,
|
||||
};
|
||||
#define MLX4_EN_MAX_RX_FRAGS 2
|
||||
#elif MJUMPAGESIZE == 8192
|
||||
#else
|
||||
#error "Unknown PAGE_SIZE"
|
||||
#endif
|
||||
|
||||
/* Maximum ring sizes */
|
||||
#define MLX4_EN_DEF_TX_QUEUE_SIZE 4096
|
||||
|
||||
@ -233,16 +209,10 @@ enum cq_type {
|
||||
#define ILLEGAL_MAC(addr) (addr == 0xffffffffffffULL || addr == 0x0)
|
||||
|
||||
struct mlx4_en_tx_info {
|
||||
bus_dmamap_t dma_map;
|
||||
struct mbuf *mb;
|
||||
u32 nr_txbb;
|
||||
u32 nr_bytes;
|
||||
u8 linear;
|
||||
u8 nr_segs;
|
||||
u8 data_offset;
|
||||
u8 inl;
|
||||
#if 0
|
||||
u8 ts_requested;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -278,6 +248,7 @@ struct mlx4_en_tx_desc {
|
||||
|
||||
struct mlx4_en_tx_ring {
|
||||
spinlock_t tx_lock;
|
||||
bus_dma_tag_t dma_tag;
|
||||
struct mlx4_hwq_resources wqres;
|
||||
u32 size ; /* number of TXBBs */
|
||||
u32 size_mask;
|
||||
@ -291,7 +262,6 @@ struct mlx4_en_tx_ring {
|
||||
u16 poll_cnt;
|
||||
int blocked;
|
||||
struct mlx4_en_tx_info *tx_info;
|
||||
u8 *bounce_buf;
|
||||
u8 queue_index;
|
||||
cpuset_t affinity_mask;
|
||||
struct buf_ring *br;
|
||||
@ -309,10 +279,8 @@ struct mlx4_en_tx_ring {
|
||||
unsigned long wake_queue;
|
||||
struct mlx4_bf bf;
|
||||
bool bf_enabled;
|
||||
struct netdev_queue *tx_queue;
|
||||
int hwtstamp_tx_type;
|
||||
spinlock_t comp_lock;
|
||||
int full_size;
|
||||
int inline_thold;
|
||||
u64 watchdog_time;
|
||||
};
|
||||
@ -322,14 +290,21 @@ struct mlx4_en_rx_desc {
|
||||
struct mlx4_wqe_data_seg data[0];
|
||||
};
|
||||
|
||||
struct mlx4_en_rx_buf {
|
||||
dma_addr_t dma;
|
||||
struct page *page;
|
||||
unsigned int page_offset;
|
||||
struct mlx4_en_rx_mbuf {
|
||||
bus_dmamap_t dma_map;
|
||||
struct mbuf *mbuf;
|
||||
};
|
||||
|
||||
struct mlx4_en_rx_spare {
|
||||
bus_dmamap_t dma_map;
|
||||
struct mbuf *mbuf;
|
||||
u64 paddr_be;
|
||||
};
|
||||
|
||||
struct mlx4_en_rx_ring {
|
||||
struct mlx4_hwq_resources wqres;
|
||||
bus_dma_tag_t dma_tag;
|
||||
struct mlx4_en_rx_spare spare;
|
||||
u32 size ; /* number of Rx descs*/
|
||||
u32 actual_size;
|
||||
u32 size_mask;
|
||||
@ -346,7 +321,7 @@ struct mlx4_en_rx_ring {
|
||||
u32 rx_mb_size;
|
||||
int qpn;
|
||||
u8 *buf;
|
||||
void *rx_info;
|
||||
struct mlx4_en_rx_mbuf *mbuf;
|
||||
unsigned long errors;
|
||||
unsigned long bytes;
|
||||
unsigned long packets;
|
||||
@ -531,12 +506,6 @@ struct en_port {
|
||||
u8 vport_num;
|
||||
};
|
||||
|
||||
struct mlx4_en_frag_info {
|
||||
u16 frag_size;
|
||||
u16 frag_prefix_size;
|
||||
};
|
||||
|
||||
|
||||
struct mlx4_en_priv {
|
||||
struct mlx4_en_dev *mdev;
|
||||
struct mlx4_en_port_profile *prof;
|
||||
@ -582,18 +551,14 @@ struct mlx4_en_priv {
|
||||
int cqe_factor;
|
||||
|
||||
struct mlx4_en_rss_map rss_map;
|
||||
__be32 ctrl_flags;
|
||||
u32 flags;
|
||||
u8 num_tx_rings_p_up;
|
||||
u32 tx_ring_num;
|
||||
u32 rx_ring_num;
|
||||
u32 rx_mb_size;
|
||||
struct mlx4_en_frag_info frag_info[MLX4_EN_MAX_RX_FRAGS];
|
||||
u16 rx_alloc_order;
|
||||
u32 rx_alloc_size;
|
||||
u32 rx_buf_size;
|
||||
u16 num_frags;
|
||||
u16 log_rx_info;
|
||||
|
||||
struct mlx4_en_tx_ring **tx_ring;
|
||||
struct mlx4_en_rx_ring *rx_ring[MAX_RX_RINGS];
|
||||
|
Loading…
Reference in New Issue
Block a user