2017-11-20 14:16:49 +00:00
|
|
|
From: Thomas Gleixner <tglx@linutronix.de>
|
2017-11-29 23:05:39 +00:00
|
|
|
Date: Thu, 23 Nov 2017 16:39:17 +0100
|
2017-11-20 14:16:49 +00:00
|
|
|
Subject: [PATCH 36/36] net/mvpp2: Replace tasklet with softirq hrtimer
|
2018-01-31 19:59:07 +00:00
|
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.14/older/patches-4.14.15-rt13.tar.xz
|
2017-11-20 14:16:49 +00:00
|
|
|
|
|
|
|
The tx_done_tasklet tasklet is used in invoke the hrtimer
|
|
|
|
(mvpp2_hr_timer_cb) in softirq context. This can be also achieved without
|
|
|
|
the tasklet but with HRTIMER_MODE_SOFT as hrtimer mode.
|
|
|
|
|
|
|
|
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
|
|
|
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
|
|
|
|
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
|
|
|
Cc: netdev@vger.kernel.org
|
2017-11-29 23:05:39 +00:00
|
|
|
Cc: "David S. Miller" <davem@davemloft.net>
|
2017-11-20 14:16:49 +00:00
|
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
|
|
---
|
|
|
|
drivers/net/ethernet/marvell/mvpp2.c | 62 ++++++++++++++---------------------
|
|
|
|
1 file changed, 25 insertions(+), 37 deletions(-)
|
|
|
|
|
|
|
|
--- a/drivers/net/ethernet/marvell/mvpp2.c
|
|
|
|
+++ b/drivers/net/ethernet/marvell/mvpp2.c
|
|
|
|
@@ -830,9 +830,8 @@ struct mvpp2_pcpu_stats {
|
|
|
|
/* Per-CPU port control */
|
|
|
|
struct mvpp2_port_pcpu {
|
|
|
|
struct hrtimer tx_done_timer;
|
|
|
|
+ struct net_device *dev;
|
|
|
|
bool timer_scheduled;
|
|
|
|
- /* Tasklet for egress finalization */
|
|
|
|
- struct tasklet_struct tx_done_tasklet;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mvpp2_queue_vector {
|
2018-01-28 14:46:47 +00:00
|
|
|
@@ -5970,46 +5969,34 @@ static void mvpp2_link_event(struct net_
|
2017-11-20 14:16:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
-static void mvpp2_timer_set(struct mvpp2_port_pcpu *port_pcpu)
|
|
|
|
-{
|
|
|
|
- ktime_t interval;
|
|
|
|
-
|
|
|
|
- if (!port_pcpu->timer_scheduled) {
|
|
|
|
- port_pcpu->timer_scheduled = true;
|
|
|
|
- interval = MVPP2_TXDONE_HRTIMER_PERIOD_NS;
|
|
|
|
- hrtimer_start(&port_pcpu->tx_done_timer, interval,
|
|
|
|
- HRTIMER_MODE_REL_PINNED);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void mvpp2_tx_proc_cb(unsigned long data)
|
|
|
|
+static enum hrtimer_restart mvpp2_hr_timer_cb(struct hrtimer *timer)
|
|
|
|
{
|
|
|
|
- struct net_device *dev = (struct net_device *)data;
|
|
|
|
- struct mvpp2_port *port = netdev_priv(dev);
|
|
|
|
- struct mvpp2_port_pcpu *port_pcpu = this_cpu_ptr(port->pcpu);
|
|
|
|
+ struct net_device *dev;
|
|
|
|
+ struct mvpp2_port *port;
|
|
|
|
+ struct mvpp2_port_pcpu *port_pcpu;
|
|
|
|
unsigned int tx_todo, cause;
|
|
|
|
|
|
|
|
+ port_pcpu = container_of(timer, struct mvpp2_port_pcpu, tx_done_timer);
|
|
|
|
+ dev = port_pcpu->dev;
|
|
|
|
+
|
|
|
|
if (!netif_running(dev))
|
|
|
|
- return;
|
|
|
|
+ return HRTIMER_NORESTART;
|
|
|
|
+
|
|
|
|
port_pcpu->timer_scheduled = false;
|
|
|
|
+ port = netdev_priv(dev);
|
|
|
|
|
|
|
|
/* Process all the Tx queues */
|
|
|
|
cause = (1 << port->ntxqs) - 1;
|
|
|
|
tx_todo = mvpp2_tx_done(port, cause, smp_processor_id());
|
|
|
|
|
|
|
|
/* Set the timer in case not all the packets were processed */
|
|
|
|
- if (tx_todo)
|
|
|
|
- mvpp2_timer_set(port_pcpu);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static enum hrtimer_restart mvpp2_hr_timer_cb(struct hrtimer *timer)
|
|
|
|
-{
|
|
|
|
- struct mvpp2_port_pcpu *port_pcpu = container_of(timer,
|
|
|
|
- struct mvpp2_port_pcpu,
|
|
|
|
- tx_done_timer);
|
|
|
|
-
|
|
|
|
- tasklet_schedule(&port_pcpu->tx_done_tasklet);
|
|
|
|
+ if (tx_todo && !port_pcpu->timer_scheduled) {
|
|
|
|
+ port_pcpu->timer_scheduled = true;
|
|
|
|
+ hrtimer_forward_now(&port_pcpu->tx_done_timer,
|
|
|
|
+ MVPP2_TXDONE_HRTIMER_PERIOD_NS);
|
|
|
|
|
|
|
|
+ return HRTIMER_RESTART;
|
|
|
|
+ }
|
|
|
|
return HRTIMER_NORESTART;
|
|
|
|
}
|
|
|
|
|
2018-01-28 14:46:47 +00:00
|
|
|
@@ -6498,7 +6485,12 @@ static int mvpp2_tx(struct sk_buff *skb,
|
2017-11-20 14:16:49 +00:00
|
|
|
txq_pcpu->count > 0) {
|
|
|
|
struct mvpp2_port_pcpu *port_pcpu = this_cpu_ptr(port->pcpu);
|
|
|
|
|
|
|
|
- mvpp2_timer_set(port_pcpu);
|
|
|
|
+ if (!port_pcpu->timer_scheduled) {
|
|
|
|
+ port_pcpu->timer_scheduled = true;
|
|
|
|
+ hrtimer_start(&port_pcpu->tx_done_timer,
|
|
|
|
+ MVPP2_TXDONE_HRTIMER_PERIOD_NS,
|
|
|
|
+ HRTIMER_MODE_REL_PINNED_SOFT);
|
|
|
|
+ }
|
|
|
|
}
|
|
|
|
|
|
|
|
return NETDEV_TX_OK;
|
2018-01-28 14:46:47 +00:00
|
|
|
@@ -6887,7 +6879,6 @@ static int mvpp2_stop(struct net_device
|
2017-11-20 14:16:49 +00:00
|
|
|
|
|
|
|
hrtimer_cancel(&port_pcpu->tx_done_timer);
|
|
|
|
port_pcpu->timer_scheduled = false;
|
|
|
|
- tasklet_kill(&port_pcpu->tx_done_tasklet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mvpp2_cleanup_rxqs(port);
|
2018-01-28 14:46:47 +00:00
|
|
|
@@ -7655,13 +7646,10 @@ static int mvpp2_port_probe(struct platf
|
2017-11-20 14:16:49 +00:00
|
|
|
port_pcpu = per_cpu_ptr(port->pcpu, cpu);
|
|
|
|
|
|
|
|
hrtimer_init(&port_pcpu->tx_done_timer, CLOCK_MONOTONIC,
|
|
|
|
- HRTIMER_MODE_REL_PINNED);
|
|
|
|
+ HRTIMER_MODE_REL_PINNED_SOFT);
|
|
|
|
port_pcpu->tx_done_timer.function = mvpp2_hr_timer_cb;
|
|
|
|
port_pcpu->timer_scheduled = false;
|
|
|
|
-
|
|
|
|
- tasklet_init(&port_pcpu->tx_done_tasklet,
|
|
|
|
- mvpp2_tx_proc_cb,
|
|
|
|
- (unsigned long)dev);
|
|
|
|
+ port_pcpu->dev = dev;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|