Commit 0ad4982c authored by Yoshihiro Shimoda's avatar Yoshihiro Shimoda Committed by David S. Miller
Browse files

net: renesas: rswitch: Fix timestamp feature after all descriptors are used



The timestamp descriptors were intended to act cyclically. Descriptors
from index 0 through gq->ring_size - 1 contain actual information, and
the last index (gq->ring_size) should have LINKFIX to indicate
the first index 0 descriptor. However, the LINKFIX value is missing,
causing the timestamp feature to stop after all descriptors are used.
To resolve this issue, set the LINKFIX to the timestamp descritors.

Reported-by: default avatarPhong Hoang <phong.hoang.wz@renesas.com>
Fixes: 33f5d733 ("net: renesas: rswitch: Improve TX timestamp accuracy")
Signed-off-by: default avatarYoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6c02568f
Loading
Loading
Loading
Loading
+22 −14
Original line number Diff line number Diff line
@@ -347,17 +347,6 @@ static int rswitch_gwca_queue_alloc(struct net_device *ndev,
	return -ENOMEM;
}

static int rswitch_gwca_ts_queue_alloc(struct rswitch_private *priv)
{
	struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;

	gq->ring_size = TS_RING_SIZE;
	gq->ts_ring = dma_alloc_coherent(&priv->pdev->dev,
					 sizeof(struct rswitch_ts_desc) *
					 (gq->ring_size + 1), &gq->ring_dma, GFP_KERNEL);
	return !gq->ts_ring ? -ENOMEM : 0;
}

static void rswitch_desc_set_dptr(struct rswitch_desc *desc, dma_addr_t addr)
{
	desc->dptrl = cpu_to_le32(lower_32_bits(addr));
@@ -533,6 +522,28 @@ static void rswitch_gwca_linkfix_free(struct rswitch_private *priv)
	gwca->linkfix_table = NULL;
}

static int rswitch_gwca_ts_queue_alloc(struct rswitch_private *priv)
{
	struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
	struct rswitch_ts_desc *desc;

	gq->ring_size = TS_RING_SIZE;
	gq->ts_ring = dma_alloc_coherent(&priv->pdev->dev,
					 sizeof(struct rswitch_ts_desc) *
					 (gq->ring_size + 1), &gq->ring_dma, GFP_KERNEL);

	if (!gq->ts_ring)
		return -ENOMEM;

	rswitch_gwca_ts_queue_fill(priv, 0, TS_RING_SIZE);
	desc = &gq->ts_ring[gq->ring_size];
	desc->desc.die_dt = DT_LINKFIX;
	rswitch_desc_set_dptr(&desc->desc, gq->ring_dma);
	INIT_LIST_HEAD(&priv->gwca.ts_info_list);

	return 0;
}

static struct rswitch_gwca_queue *rswitch_gwca_get(struct rswitch_private *priv)
{
	struct rswitch_gwca_queue *gq;
@@ -1780,9 +1791,6 @@ static int rswitch_init(struct rswitch_private *priv)
	if (err < 0)
		goto err_ts_queue_alloc;

	rswitch_gwca_ts_queue_fill(priv, 0, TS_RING_SIZE);
	INIT_LIST_HEAD(&priv->gwca.ts_info_list);

	for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
		err = rswitch_device_alloc(priv, i);
		if (err < 0) {