From patchwork Sun Nov 22 07:53:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcin Wojtas X-Patchwork-Id: 7675661 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 0CE17BF90C for ; Sun, 22 Nov 2015 08:00:17 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 088DF2064F for ; Sun, 22 Nov 2015 08:00:16 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 030F420647 for ; Sun, 22 Nov 2015 08:00:15 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1a0PXO-00040t-75; Sun, 22 Nov 2015 07:58:18 +0000 Received: from mail-lf0-x22d.google.com ([2a00:1450:4010:c07::22d]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a0PTW-0008TK-H0 for linux-arm-kernel@lists.infradead.org; Sun, 22 Nov 2015 07:54:20 +0000 Received: by lffu14 with SMTP id u14so91375660lff.1 for ; Sat, 21 Nov 2015 23:53:56 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7x/qPCmlCpqOv19PD6SSR6pYHTdwHoJ5qOW2CwZok30=; b=BzXBQeKJSHTISAhQ1NlIAWY/514n2i2NbP9kVkDTNBQ89PtUmnYKVMJiJ2gJGvPr0C MXHlp+E8qCB/yNOArYMVAvtVVtvrlCPTN31SzgMP4ROd562dJY+g8IkqoOgbCQbx0ryg lW1wamEIUFB8rznvIO26yCWB1r/4baeleBcyzHHLeZ/42Uh0VSxOenevl/DbLBgRCb8Q eIIwWPCpA5nEZaLPNDEd3KLkOrZVZ86c4RhorlhSHNnwnxX9QIORWOKh6a0WEmTN8t+U +YNDzTk8dxHix2RyzURbg1kDse2H1q+2Le+9wq72lr4aVuBsqDHrIiOGkjAkogcUMsTe JtyA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7x/qPCmlCpqOv19PD6SSR6pYHTdwHoJ5qOW2CwZok30=; b=Rh34s+mSx2VwZ72+Kpr6cKJambBblD3rQZ6YTa4Oqb2T2vcJb1JCGeZNp0LOVm9Bg+ WwmfRxcHTVJUf8izBbNo2kfLqKuxdA9AQaKzotTrpwSrH9yz2ArVROU7vw9waHXukZXh fm7rzasvhku00403ZkQTjshgji3Zxt+VJUVRMW1V23NA6/QZOX9ADef28cAEAdgj+evY gl1rPliQZRaFi03jSEhFTlo6pyf7N2iHxURBgxssz9lto7haU+M3uHwDf0rfZCVVavCn h4R/OmcwejW0grDSBK2DiHk5RjEXyV/O77dIUS62HV5jj8+vQRNIQoAGwga2JUQcpaS0 4jnw== X-Gm-Message-State: ALoCoQk/qB5YXCgSZA6NqW+OUJoGpLZcKMVt0EORHiwEaJ5lj1vaQAA87clPZ3nTDuEQOmOLobTF X-Received: by 10.25.26.68 with SMTP id a65mr251028lfa.72.1448178836464; Sat, 21 Nov 2015 23:53:56 -0800 (PST) Received: from enkidu.semihalf.local (cardhu.semihalf.com. [213.17.239.108]) by smtp.gmail.com with ESMTPSA id y79sm1010840lfd.45.2015.11.21.23.53.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 21 Nov 2015 23:53:55 -0800 (PST) From: Marcin Wojtas To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org Subject: [PATCH 06/13] net: mvneta: enable mixed egress processing using HR timer Date: Sun, 22 Nov 2015 08:53:52 +0100 Message-Id: <1448178839-3541-7-git-send-email-mw@semihalf.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1448178839-3541-1-git-send-email-mw@semihalf.com> References: <1448178839-3541-1-git-send-email-mw@semihalf.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151121_235419_030975_3388A776 X-CRM114-Status: GOOD ( 17.41 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: thomas.petazzoni@free-electrons.com, andrew@lunn.ch, linux@arm.linux.org.uk, jason@lakedaemon.net, myair@marvell.com, jaz@semihalf.com, simon.guinot@sequanux.org, xswang@marvell.com, nadavh@marvell.com, alior@marvell.com, tn@semihalf.com, gregory.clement@free-electrons.com, nitroshift@yahoo.com, mw@semihalf.com, davem@davemloft.net, sebastian.hesselbarth@gmail.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Mixed approach allows using higher interrupt threshold (increased back to 15 packets), useful in high throughput. In case of small amount of data or very short TX queues HR timer ensures releasing buffers with small latency. Along with existing tx_done processing by coalescing interrupts this commit enables triggering HR timer each time the packets are sent. Time threshold can also be configured, using ethtool. Signed-off-by: Marcin Wojtas Signed-off-by: Simon Guinot --- drivers/net/ethernet/marvell/mvneta.c | 89 +++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 9c9e858..f5acaf6 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include #include @@ -226,7 +228,8 @@ /* Various constants */ /* Coalescing */ -#define MVNETA_TXDONE_COAL_PKTS 1 +#define MVNETA_TXDONE_COAL_PKTS 15 +#define MVNETA_TXDONE_COAL_USEC 100 #define MVNETA_RX_COAL_PKTS 32 #define MVNETA_RX_COAL_USEC 100 @@ -356,6 +359,11 @@ struct mvneta_port { struct net_device *dev; struct notifier_block cpu_notifier; + /* Egress finalization */ + struct tasklet_struct tx_done_tasklet; + struct hrtimer tx_done_timer; + bool timer_scheduled; + /* Core clock */ struct clk *clk; u8 mcast_count[256]; @@ -481,6 +489,7 @@ struct mvneta_tx_queue { int txq_get_index; u32 done_pkts_coal; + u32 done_time_coal; /* Virtual address of the TX DMA descriptors array */ struct mvneta_tx_desc *descs; @@ -1791,6 +1800,30 @@ error: return -ENOMEM; } +/* Trigger HR timer for TX processing */ +static void mvneta_timer_set(struct mvneta_port *pp) +{ + ktime_t interval; + + if (!pp->timer_scheduled) { + pp->timer_scheduled = true; + interval = ktime_set(0, pp->txqs[0].done_time_coal * 1000); + hrtimer_start(&pp->tx_done_timer, interval, + HRTIMER_MODE_REL_PINNED); + } +} + +/* TX processing HR timer callback */ +static enum hrtimer_restart mvneta_hr_timer_cb(struct hrtimer *timer) +{ + struct mvneta_port *pp = container_of(timer, struct mvneta_port, + tx_done_timer); + + tasklet_schedule(&pp->tx_done_tasklet); + + return HRTIMER_NORESTART; +} + /* Main tx processing */ static int mvneta_tx(struct sk_buff *skb, struct net_device *dev) { @@ -1862,10 +1895,13 @@ out: if (txq->count >= txq->tx_stop_threshold) netif_tx_stop_queue(nq); - if (!skb->xmit_more || netif_xmit_stopped(nq)) + if (!skb->xmit_more || netif_xmit_stopped(nq)) { mvneta_txq_pend_desc_add(pp, txq, frags); - else + if (txq->done_time_coal && !pp->timer_scheduled) + mvneta_timer_set(pp); + } else { txq->pending += frags; + } u64_stats_update_begin(&stats->syncp); stats->tx_packets++; @@ -1902,6 +1938,7 @@ static void mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done) { struct mvneta_tx_queue *txq; struct netdev_queue *nq; + unsigned int tx_todo = 0; while (cause_tx_done) { txq = mvneta_tx_done_policy(pp, cause_tx_done); @@ -1909,12 +1946,40 @@ static void mvneta_tx_done_gbe(struct mvneta_port *pp, u32 cause_tx_done) nq = netdev_get_tx_queue(pp->dev, txq->id); __netif_tx_lock(nq, smp_processor_id()); - if (txq->count) + if (txq->count) { mvneta_txq_done(pp, txq); + tx_todo += txq->count; + } __netif_tx_unlock(nq); cause_tx_done &= ~((1 << txq->id)); } + + if (!pp->txqs[0].done_time_coal) + return; + + /* Set the timer in case not all the packets were + * processed. Otherwise attempt to cancel timer. + */ + if (tx_todo) + mvneta_timer_set(pp); + else if (pp->timer_scheduled) + hrtimer_cancel(&pp->tx_done_timer); +} + +/* TX done processing tasklet */ +static void mvneta_tx_done_proc(unsigned long data) +{ + struct net_device *dev = (struct net_device *)data; + struct mvneta_port *pp = netdev_priv(dev); + + if (!netif_running(dev)) + return; + + pp->timer_scheduled = false; + + /* Process all Tx queues */ + mvneta_tx_done_gbe(pp, (1 << txq_number) - 1); } /* Compute crc8 of the specified address, using a unique algorithm , @@ -2910,6 +2975,11 @@ static int mvneta_stop(struct net_device *dev) for_each_present_cpu(cpu) smp_call_function_single(cpu, mvneta_percpu_disable, pp, true); free_percpu_irq(dev->irq, pp->ports); + + hrtimer_cancel(&pp->tx_done_timer); + pp->timer_scheduled = false; + tasklet_kill(&pp->tx_done_tasklet); + mvneta_cleanup_rxqs(pp); mvneta_cleanup_txqs(pp); @@ -2967,6 +3037,7 @@ static int mvneta_ethtool_set_coalesce(struct net_device *dev, for (queue = 0; queue < txq_number; queue++) { struct mvneta_tx_queue *txq = &pp->txqs[queue]; + txq->done_time_coal = c->tx_coalesce_usecs; txq->done_pkts_coal = c->tx_max_coalesced_frames; mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal); } @@ -2983,6 +3054,7 @@ static int mvneta_ethtool_get_coalesce(struct net_device *dev, c->rx_coalesce_usecs = pp->rxqs[0].time_coal; c->rx_max_coalesced_frames = pp->rxqs[0].pkts_coal; + c->tx_coalesce_usecs = pp->txqs[0].done_time_coal; c->tx_max_coalesced_frames = pp->txqs[0].done_pkts_coal; return 0; } @@ -3146,6 +3218,7 @@ static int mvneta_init(struct device *dev, struct mvneta_port *pp) txq->id = queue; txq->size = pp->tx_ring_size; txq->done_pkts_coal = MVNETA_TXDONE_COAL_PKTS; + txq->done_time_coal = MVNETA_TXDONE_COAL_USEC; } pp->rxqs = devm_kcalloc(dev, rxq_number, sizeof(struct mvneta_rx_queue), @@ -3388,6 +3461,14 @@ static int mvneta_probe(struct platform_device *pdev) port->pp = pp; } + hrtimer_init(&pp->tx_done_timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_PINNED); + pp->tx_done_timer.function = mvneta_hr_timer_cb; + pp->timer_scheduled = false; + + tasklet_init(&pp->tx_done_tasklet, mvneta_tx_done_proc, + (unsigned long)dev); + dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; dev->hw_features |= dev->features; dev->vlan_features |= dev->features;