Skip to content

Commit

Permalink
platform/mellanox: mlxbf-tmfifo: Drop the Rx packet if no more descri…
Browse files Browse the repository at this point in the history
…ptors

[ Upstream commit 78034cb ]

This commit fixes tmfifo console stuck issue when the virtual
networking interface is in down state. In such case, the network
Rx descriptors runs out and causes the Rx network packet staying
in the head of the tmfifo thus blocking the console packets. The
fix is to drop the Rx network packet when no more Rx descriptors.
Function name mlxbf_tmfifo_release_pending_pkt() is also renamed
to mlxbf_tmfifo_release_pkt() to be more approperiate.

Fixes: 1357dfd ("platform/mellanox: Add TmFifo driver for Mellanox BlueField Soc")
Signed-off-by: Liming Sun <limings@nvidia.com>
Reviewed-by: Vadim Pasternak <vadimp@nvidia.com>
Reviewed-by: David Thompson <davthompson@nvidia.com>
Link: https://lore.kernel.org/r/8c0177dc938ae03f52ff7e0b62dbeee74b7bec09.1693322547.git.limings@nvidia.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Liming Sun authored and gregkh committed Sep 19, 2023
1 parent af8085e commit 8efa4d5
Showing 1 changed file with 49 additions and 17 deletions.
66 changes: 49 additions & 17 deletions drivers/platform/mellanox/mlxbf-tmfifo.c
Expand Up @@ -59,6 +59,7 @@ struct mlxbf_tmfifo;
* @vq: pointer to the virtio virtqueue
* @desc: current descriptor of the pending packet
* @desc_head: head descriptor of the pending packet
* @drop_desc: dummy desc for packet dropping
* @cur_len: processed length of the current descriptor
* @rem_len: remaining length of the pending packet
* @pkt_len: total length of the pending packet
Expand All @@ -75,6 +76,7 @@ struct mlxbf_tmfifo_vring {
struct virtqueue *vq;
struct vring_desc *desc;
struct vring_desc *desc_head;
struct vring_desc drop_desc;
int cur_len;
int rem_len;
u32 pkt_len;
Expand All @@ -86,6 +88,14 @@ struct mlxbf_tmfifo_vring {
struct mlxbf_tmfifo *fifo;
};

/* Check whether vring is in drop mode. */
#define IS_VRING_DROP(_r) ({ \
typeof(_r) (r) = (_r); \
(r->desc_head == &r->drop_desc ? true : false); })

/* A stub length to drop maximum length packet. */
#define VRING_DROP_DESC_MAX_LEN GENMASK(15, 0)

/* Interrupt types. */
enum {
MLXBF_TM_RX_LWM_IRQ,
Expand Down Expand Up @@ -262,6 +272,7 @@ static int mlxbf_tmfifo_alloc_vrings(struct mlxbf_tmfifo *fifo,
vring->align = SMP_CACHE_BYTES;
vring->index = i;
vring->vdev_id = tm_vdev->vdev.id.device;
vring->drop_desc.len = VRING_DROP_DESC_MAX_LEN;
dev = &tm_vdev->vdev.dev;

size = vring_size(vring->num, vring->align);
Expand Down Expand Up @@ -367,7 +378,7 @@ static u32 mlxbf_tmfifo_get_pkt_len(struct mlxbf_tmfifo_vring *vring,
return len;
}

static void mlxbf_tmfifo_release_pending_pkt(struct mlxbf_tmfifo_vring *vring)
static void mlxbf_tmfifo_release_pkt(struct mlxbf_tmfifo_vring *vring)
{
struct vring_desc *desc_head;
u32 len = 0;
Expand Down Expand Up @@ -596,19 +607,25 @@ static void mlxbf_tmfifo_rxtx_word(struct mlxbf_tmfifo_vring *vring,

if (vring->cur_len + sizeof(u64) <= len) {
/* The whole word. */
if (is_rx)
memcpy(addr + vring->cur_len, &data, sizeof(u64));
else
memcpy(&data, addr + vring->cur_len, sizeof(u64));
if (!IS_VRING_DROP(vring)) {
if (is_rx)
memcpy(addr + vring->cur_len, &data,
sizeof(u64));
else
memcpy(&data, addr + vring->cur_len,
sizeof(u64));
}
vring->cur_len += sizeof(u64);
} else {
/* Leftover bytes. */
if (is_rx)
memcpy(addr + vring->cur_len, &data,
len - vring->cur_len);
else
memcpy(&data, addr + vring->cur_len,
len - vring->cur_len);
if (!IS_VRING_DROP(vring)) {
if (is_rx)
memcpy(addr + vring->cur_len, &data,
len - vring->cur_len);
else
memcpy(&data, addr + vring->cur_len,
len - vring->cur_len);
}
vring->cur_len = len;
}

Expand Down Expand Up @@ -709,8 +726,16 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
/* Get the descriptor of the next packet. */
if (!vring->desc) {
desc = mlxbf_tmfifo_get_next_pkt(vring, is_rx);
if (!desc)
return false;
if (!desc) {
/* Drop next Rx packet to avoid stuck. */
if (is_rx) {
desc = &vring->drop_desc;
vring->desc_head = desc;
vring->desc = desc;
} else {
return false;
}
}
} else {
desc = vring->desc;
}
Expand Down Expand Up @@ -743,17 +768,24 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
vring->rem_len -= len;

/* Get the next desc on the chain. */
if (vring->rem_len > 0 &&
if (!IS_VRING_DROP(vring) && vring->rem_len > 0 &&
(virtio16_to_cpu(vdev, desc->flags) & VRING_DESC_F_NEXT)) {
idx = virtio16_to_cpu(vdev, desc->next);
desc = &vr->desc[idx];
goto mlxbf_tmfifo_desc_done;
}

/* Done and release the pending packet. */
mlxbf_tmfifo_release_pending_pkt(vring);
/* Done and release the packet. */
desc = NULL;
fifo->vring[is_rx] = NULL;
if (!IS_VRING_DROP(vring)) {
mlxbf_tmfifo_release_pkt(vring);
} else {
vring->pkt_len = 0;
vring->desc_head = NULL;
vring->desc = NULL;
return false;
}

/*
* Make sure the load/store are in order before
Expand Down Expand Up @@ -933,7 +965,7 @@ static void mlxbf_tmfifo_virtio_del_vqs(struct virtio_device *vdev)

/* Release the pending packet. */
if (vring->desc)
mlxbf_tmfifo_release_pending_pkt(vring);
mlxbf_tmfifo_release_pkt(vring);
vq = vring->vq;
if (vq) {
vring->vq = NULL;
Expand Down

0 comments on commit 8efa4d5

Please sign in to comment.