Commit ecb9f80d authored by Thomas Gleixner's avatar Thomas Gleixner Committed by David S. Miller

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: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 03eb57bb
...@@ -829,9 +829,8 @@ struct mvpp2_pcpu_stats { ...@@ -829,9 +829,8 @@ struct mvpp2_pcpu_stats {
/* Per-CPU port control */ /* Per-CPU port control */
struct mvpp2_port_pcpu { struct mvpp2_port_pcpu {
struct hrtimer tx_done_timer; struct hrtimer tx_done_timer;
struct net_device *dev;
bool timer_scheduled; bool timer_scheduled;
/* Tasklet for egress finalization */
struct tasklet_struct tx_done_tasklet;
}; };
struct mvpp2_queue_vector { struct mvpp2_queue_vector {
......
...@@ -2651,31 +2651,21 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id) ...@@ -2651,31 +2651,21 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
return IRQ_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 net_device *dev;
struct mvpp2_port *port = netdev_priv(dev); struct mvpp2_port *port;
struct mvpp2_port_pcpu *port_pcpu; struct mvpp2_port_pcpu *port_pcpu;
unsigned int tx_todo, cause; unsigned int tx_todo, cause;
port_pcpu = per_cpu_ptr(port->pcpu, port_pcpu = container_of(timer, struct mvpp2_port_pcpu, tx_done_timer);
mvpp2_cpu_to_thread(port->priv, smp_processor_id())); dev = port_pcpu->dev;
if (!netif_running(dev)) if (!netif_running(dev))
return; return HRTIMER_NORESTART;
port_pcpu->timer_scheduled = false; port_pcpu->timer_scheduled = false;
port = netdev_priv(dev);
/* Process all the Tx queues */ /* Process all the Tx queues */
cause = (1 << port->ntxqs) - 1; cause = (1 << port->ntxqs) - 1;
...@@ -2683,18 +2673,13 @@ static void mvpp2_tx_proc_cb(unsigned long data) ...@@ -2683,18 +2673,13 @@ static void mvpp2_tx_proc_cb(unsigned long data)
mvpp2_cpu_to_thread(port->priv, smp_processor_id())); mvpp2_cpu_to_thread(port->priv, smp_processor_id()));
/* Set the timer in case not all the packets were processed */ /* Set the timer in case not all the packets were processed */
if (tx_todo) if (tx_todo && !port_pcpu->timer_scheduled) {
mvpp2_timer_set(port_pcpu); port_pcpu->timer_scheduled = true;
} hrtimer_forward_now(&port_pcpu->tx_done_timer,
MVPP2_TXDONE_HRTIMER_PERIOD_NS);
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);
return HRTIMER_RESTART;
}
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
...@@ -3182,7 +3167,12 @@ static netdev_tx_t mvpp2_tx(struct sk_buff *skb, struct net_device *dev) ...@@ -3182,7 +3167,12 @@ static netdev_tx_t mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
txq_pcpu->count > 0) { txq_pcpu->count > 0) {
struct mvpp2_port_pcpu *port_pcpu = per_cpu_ptr(port->pcpu, thread); 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)) if (test_bit(thread, &port->priv->lock_map))
...@@ -3619,7 +3609,6 @@ static int mvpp2_stop(struct net_device *dev) ...@@ -3619,7 +3609,6 @@ static int mvpp2_stop(struct net_device *dev)
hrtimer_cancel(&port_pcpu->tx_done_timer); hrtimer_cancel(&port_pcpu->tx_done_timer);
port_pcpu->timer_scheduled = false; port_pcpu->timer_scheduled = false;
tasklet_kill(&port_pcpu->tx_done_tasklet);
} }
} }
mvpp2_cleanup_rxqs(port); mvpp2_cleanup_rxqs(port);
...@@ -5183,13 +5172,10 @@ static int mvpp2_port_probe(struct platform_device *pdev, ...@@ -5183,13 +5172,10 @@ static int mvpp2_port_probe(struct platform_device *pdev,
port_pcpu = per_cpu_ptr(port->pcpu, thread); port_pcpu = per_cpu_ptr(port->pcpu, thread);
hrtimer_init(&port_pcpu->tx_done_timer, CLOCK_MONOTONIC, 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->tx_done_timer.function = mvpp2_hr_timer_cb;
port_pcpu->timer_scheduled = false; port_pcpu->timer_scheduled = false;
port_pcpu->dev = dev;
tasklet_init(&port_pcpu->tx_done_tasklet,
mvpp2_tx_proc_cb,
(unsigned long)dev);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment