net/mvpp2: Replace tasklet with softirq hrtimer
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: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
03eb57bb89
commit
ecb9f80db2
@@ -829,9 +829,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 {
|
||||
|
@@ -2651,31 +2651,21 @@ handled:
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void mvpp2_timer_set(struct mvpp2_port_pcpu *port_pcpu)
|
||||
static enum hrtimer_restart mvpp2_hr_timer_cb(struct hrtimer *timer)
|
||||
{
|
||||
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)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)data;
|
||||
struct mvpp2_port *port = netdev_priv(dev);
|
||||
struct net_device *dev;
|
||||
struct mvpp2_port *port;
|
||||
struct mvpp2_port_pcpu *port_pcpu;
|
||||
unsigned int tx_todo, cause;
|
||||
|
||||
port_pcpu = per_cpu_ptr(port->pcpu,
|
||||
mvpp2_cpu_to_thread(port->priv, smp_processor_id()));
|
||||
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;
|
||||
@@ -2683,18 +2673,13 @@ static void mvpp2_tx_proc_cb(unsigned long data)
|
||||
mvpp2_cpu_to_thread(port->priv, 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;
|
||||
}
|
||||
|
||||
@@ -3182,7 +3167,12 @@ out:
|
||||
txq_pcpu->count > 0) {
|
||||
struct mvpp2_port_pcpu *port_pcpu = per_cpu_ptr(port->pcpu, thread);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(thread, &port->priv->lock_map))
|
||||
@@ -3619,7 +3609,6 @@ static int mvpp2_stop(struct net_device *dev)
|
||||
|
||||
hrtimer_cancel(&port_pcpu->tx_done_timer);
|
||||
port_pcpu->timer_scheduled = false;
|
||||
tasklet_kill(&port_pcpu->tx_done_tasklet);
|
||||
}
|
||||
}
|
||||
mvpp2_cleanup_rxqs(port);
|
||||
@@ -5183,13 +5172,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
|
||||
port_pcpu = per_cpu_ptr(port->pcpu, thread);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user