Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -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 {
+22 −36
Original line number Diff line number Diff line
@@ -2651,31 +2651,21 @@ static irqreturn_t mvpp2_link_status_isr(int irq, void *dev_id)
	return IRQ_HANDLED;
}

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 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 @@ static netdev_tx_t mvpp2_tx(struct sk_buff *skb, struct net_device *dev)
	    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;
		}
	}