This allows us to optimise polling and receive processing for the GbEth
IP used in the RZ/G2L Soc family, without affecting the wider family of
R-Car based devices.
Signed-off-by: Paul Barker <[email protected]>
---
drivers/net/ethernet/renesas/ravb.h | 2 +-
drivers/net/ethernet/renesas/ravb_main.c | 74 ++++++++++++++++++------
2 files changed, 58 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index 3cf869fb9a68..9e9cf0d36d72 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -1050,7 +1050,7 @@ struct ravb_hw_info {
void (*rx_ring_free)(struct net_device *ndev, int q);
void (*rx_ring_format)(struct net_device *ndev, int q);
void *(*alloc_rx_desc)(struct net_device *ndev, int q);
- bool (*receive)(struct net_device *ndev, int *quota, int q);
+ int (*poll)(struct napi_struct *napi, int budget);
void (*set_rate)(struct net_device *ndev);
int (*set_feature)(struct net_device *ndev, netdev_features_t features);
int (*dmac_init)(struct net_device *ndev);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 4976ecc91cde..c9464c1731b4 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -1069,15 +1069,6 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
return boguscnt <= 0;
}
-/* Packet receive function for Ethernet AVB */
-static bool ravb_rx(struct net_device *ndev, int *quota, int q)
-{
- struct ravb_private *priv = netdev_priv(ndev);
- const struct ravb_hw_info *info = priv->info;
-
- return info->receive(ndev, quota, q);
-}
-
static void ravb_rcv_snd_disable(struct net_device *ndev)
{
/* Disable TX and RX */
@@ -1345,7 +1336,56 @@ static irqreturn_t ravb_nc_interrupt(int irq, void *dev_id)
return ravb_dma_interrupt(irq, dev_id, RAVB_NC);
}
-static int ravb_poll(struct napi_struct *napi, int budget)
+static int ravb_poll_gbeth(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;
+ unsigned long flags;
+ int q = napi - priv->napi;
+ int mask = BIT(q);
+ int quota = budget;
+
+ /* Processing RX Descriptor Ring */
+ /* Clear RX interrupt */
+ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
+ if (ravb_rx_gbeth(ndev, "a, q))
+ goto out;
+
+ /* Processing TX Descriptor Ring */
+ spin_lock_irqsave(&priv->lock, flags);
+ /* Clear TX interrupt */
+ ravb_write(ndev, ~(mask | TIS_RESERVED), TIS);
+ ravb_tx_free(ndev, q, true);
+ netif_wake_subqueue(ndev, q);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ napi_complete(napi);
+
+ /* Re-enable RX/TX interrupts */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!info->irq_en_dis) {
+ ravb_modify(ndev, RIC0, mask, mask);
+ ravb_modify(ndev, TIC, mask, mask);
+ } else {
+ ravb_write(ndev, mask, RIE0);
+ ravb_write(ndev, mask, TIE);
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Receive error message handling */
+ priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors;
+ if (info->nc_queues)
+ priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
+ if (priv->rx_over_errors != ndev->stats.rx_over_errors)
+ ndev->stats.rx_over_errors = priv->rx_over_errors;
+ if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
+ ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
+out:
+ return budget - quota;
+}
+
+static int ravb_poll_rcar(struct napi_struct *napi, int budget)
{
struct net_device *ndev = napi->dev;
struct ravb_private *priv = netdev_priv(ndev);
@@ -1358,7 +1398,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
/* Processing RX Descriptor Ring */
/* Clear RX interrupt */
ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
- if (ravb_rx(ndev, "a, q))
+ if (ravb_rx_rcar(ndev, "a, q))
goto out;
/* Processing TX Descriptor Ring */
@@ -2559,7 +2599,7 @@ static const struct ravb_hw_info ravb_gen3_hw_info = {
.rx_ring_free = ravb_rx_ring_free_rcar,
.rx_ring_format = ravb_rx_ring_format_rcar,
.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
- .receive = ravb_rx_rcar,
+ .poll = ravb_poll_rcar,
.set_rate = ravb_set_rate_rcar,
.set_feature = ravb_set_features_rcar,
.dmac_init = ravb_dmac_init_rcar,
@@ -2585,7 +2625,7 @@ static const struct ravb_hw_info ravb_gen2_hw_info = {
.rx_ring_free = ravb_rx_ring_free_rcar,
.rx_ring_format = ravb_rx_ring_format_rcar,
.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
- .receive = ravb_rx_rcar,
+ .poll = ravb_poll_rcar,
.set_rate = ravb_set_rate_rcar,
.set_feature = ravb_set_features_rcar,
.dmac_init = ravb_dmac_init_rcar,
@@ -2608,7 +2648,7 @@ static const struct ravb_hw_info ravb_rzv2m_hw_info = {
.rx_ring_free = ravb_rx_ring_free_rcar,
.rx_ring_format = ravb_rx_ring_format_rcar,
.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
- .receive = ravb_rx_rcar,
+ .poll = ravb_poll_rcar,
.set_rate = ravb_set_rate_rcar,
.set_feature = ravb_set_features_rcar,
.dmac_init = ravb_dmac_init_rcar,
@@ -2633,7 +2673,7 @@ static const struct ravb_hw_info gbeth_hw_info = {
.rx_ring_free = ravb_rx_ring_free_gbeth,
.rx_ring_format = ravb_rx_ring_format_gbeth,
.alloc_rx_desc = ravb_alloc_rx_desc_gbeth,
- .receive = ravb_rx_gbeth,
+ .poll = ravb_poll_gbeth,
.set_rate = ravb_set_rate_gbeth,
.set_feature = ravb_set_features_gbeth,
.dmac_init = ravb_dmac_init_gbeth,
@@ -2990,9 +3030,9 @@ static int ravb_probe(struct platform_device *pdev)
goto out_dma_free;
}
- netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll);
+ netif_napi_add(ndev, &priv->napi[RAVB_BE], info->poll);
if (info->nc_queues)
- netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll);
+ netif_napi_add(ndev, &priv->napi[RAVB_NC], info->poll);
/* Network device register */
error = register_netdev(ndev);
--
2.39.2