[RFC/PATCH 12/18] ravb: Add timestamp to struct ravb_hw_info
From: Biju Das <biju.das.jz@bp.renesas.com>
Date: 2021-09-23 14:09:04
Also in:
linux-renesas-soc
Subsystem:
networking drivers, renesas ethernet avb driver, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Niklas Söderlund, Linus Torvalds
R-Car AVB-DMAC supports timestamp feature. Add a timestamp hw feature bit to struct ravb_hw_info to add this feature only for R-Car. Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com> --- drivers/net/ethernet/renesas/ravb.h | 2 + drivers/net/ethernet/renesas/ravb_main.c | 68 +++++++++++++++--------- 2 files changed, 45 insertions(+), 25 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index ab4909244276..2505de5d4a28 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h@@ -1034,6 +1034,7 @@ struct ravb_hw_info { unsigned mii_rgmii_selection:1; /* E-MAC supports mii/rgmii selection */ unsigned half_duplex:1; /* E-MAC supports half duplex mode */ unsigned rx_2k_buffers:1; /* AVB-DMAC has Max 2K buf size on RX */ + unsigned timestamp:1; /* AVB-DMAC has timestamp */ }; struct ravb_private {
@@ -1089,6 +1090,7 @@ struct ravb_private { unsigned int num_tx_desc; /* TX descriptors per packet */ int duplex; + struct ravb_rx_desc *rgeth_rx_ring[NUM_RX_QUEUE]; const struct ravb_hw_info *info; struct reset_control *rstc;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 9c0d35f4b221..2c375002ebcb 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c@@ -949,11 +949,14 @@ static bool ravb_queue_interrupt(struct net_device *ndev, int q) static bool ravb_timestamp_interrupt(struct net_device *ndev) { + struct ravb_private *priv = netdev_priv(ndev); + const struct ravb_hw_info *info = priv->info; u32 tis = ravb_read(ndev, TIS); if (tis & TIS_TFUF) { ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS); - ravb_get_tx_tstamp(ndev); + if (info->timestamp) + ravb_get_tx_tstamp(ndev); return true; } return false;
@@ -1071,16 +1074,24 @@ static int ravb_poll(struct napi_struct *napi, int budget) struct net_device *ndev = napi->dev; struct ravb_private *priv = netdev_priv(ndev); const struct ravb_hw_info *info = priv->info; + struct ravb_rx_desc *desc; unsigned long flags; int q = napi - priv->napi; int mask = BIT(q); int quota = budget; + unsigned int entry; + if (!info->timestamp) { + entry = priv->cur_rx[q] % priv->num_rx_ring[q]; + desc = &priv->rgeth_rx_ring[q][entry]; + } /* Processing RX Descriptor Ring */ /* Clear RX interrupt */ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0); - if (ravb_rx(ndev, "a, q)) - goto out; + if (info->timestamp || desc->die_dt != DT_FEMPTY) { + if (ravb_rx(ndev, "a, q)) + goto out; + } /* Processing TX Descriptor Ring */ spin_lock_irqsave(&priv->lock, flags);
@@ -1689,6 +1700,7 @@ static void ravb_tx_timeout_work(struct work_struct *work) static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) { struct ravb_private *priv = netdev_priv(ndev); + const struct ravb_hw_info *info = priv->info; unsigned int num_tx_desc = priv->num_tx_desc; u16 q = skb_get_queue_mapping(skb); struct ravb_tstamp_skb *ts_skb;
@@ -1765,28 +1777,30 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) desc->dptr = cpu_to_le32(dma_addr); /* TX timestamp required */ - if (q == RAVB_NC) { - ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC); - if (!ts_skb) { - if (num_tx_desc > 1) { - desc--; - dma_unmap_single(ndev->dev.parent, dma_addr, - len, DMA_TO_DEVICE); + if (info->timestamp) { + if (q == RAVB_NC) { + ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC); + if (!ts_skb) { + if (num_tx_desc > 1) { + desc--; + dma_unmap_single(ndev->dev.parent, dma_addr, + len, DMA_TO_DEVICE); + } + goto unmap; } - goto unmap; + ts_skb->skb = skb_get(skb); + ts_skb->tag = priv->ts_skb_tag++; + priv->ts_skb_tag &= 0x3ff; + list_add_tail(&ts_skb->list, &priv->ts_skb_list); + + /* TAG and timestamp required flag */ + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR; + desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12); } - ts_skb->skb = skb_get(skb); - ts_skb->tag = priv->ts_skb_tag++; - priv->ts_skb_tag &= 0x3ff; - list_add_tail(&ts_skb->list, &priv->ts_skb_list); - /* TAG and timestamp required flag */ - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR; - desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12); + skb_tx_timestamp(skb); } - - skb_tx_timestamp(skb); /* Descriptor type must be set after all the above writes */ dma_wmb(); if (num_tx_desc > 1) {
@@ -1897,10 +1911,12 @@ static int ravb_close(struct net_device *ndev) "device will be stopped after h/w processes are done.\n"); /* Clear the timestamp list */ - list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) { - list_del(&ts_skb->list); - kfree_skb(ts_skb->skb); - kfree(ts_skb); + if (info->timestamp) { + list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) { + list_del(&ts_skb->list); + kfree_skb(ts_skb->skb); + kfree(ts_skb); + } } /* PHY disconnect */
@@ -2165,6 +2181,7 @@ static const struct ravb_hw_info ravb_gen3_hw_info = { .multi_tsrq = 1, .magic_pkt = 1, .rx_2k_buffers = 1, + .timestamp = 1, }; static const struct ravb_hw_info ravb_gen2_hw_info = {
@@ -2186,6 +2203,7 @@ static const struct ravb_hw_info ravb_gen2_hw_info = { .multi_tsrq = 1, .magic_pkt = 1, .rx_2k_buffers = 1, + .timestamp = 1, }; static const struct ravb_hw_info rgeth_hw_info = {
--
2.17.1