From patchwork Wed Apr 6 02:25:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Troy Kisky X-Patchwork-Id: 8757581 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 48085C0553 for ; Wed, 6 Apr 2016 02:31:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 73FAE202F2 for ; Wed, 6 Apr 2016 02:31:14 +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 64B9C20295 for ; Wed, 6 Apr 2016 02:31:13 +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 1andDw-0008I8-2N; Wed, 06 Apr 2016 02:29:40 +0000 Received: from mail-pa0-x22d.google.com ([2607:f8b0:400e:c03::22d]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1andCv-0007jK-PA for linux-arm-kernel@lists.infradead.org; Wed, 06 Apr 2016 02:28:39 +0000 Received: by mail-pa0-x22d.google.com with SMTP id bx7so6607093pad.3 for ; Tue, 05 Apr 2016 19:28:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=boundarydevices-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=RYaTSFz5DM3c+xWRtK9u0uWhI5NF9uy2TtCzLCwP0SU=; b=wv4CTzgRaeKdKTYsdWVbM4+fR6AlF7HOYsQSrmn3mNSxR4H98V2Ox9hc9X6IK4JCGy GL+Ub6epMaH4HcqitLOMRsmAecOuYU7cgRoecK0OUAztcWWb1aTAQRGKvL4lL6R1sB7b OTNjstBJg/sbmIPnI4Jm+K4/r6odjShRHX9+OD9bnjjyRYAKk+Rl7pvW0EmkJZ82JVa8 FUYPs2kzoAk2S4/k4+CIq4KMXE6BWU/Gsg2jAB3Og0H+eQ98YUv7Eiay7KhK/KXFysUD LCFQZfZCjNXdOT/2WzabO8fi73vLXM7yq0VPcg6X8GqIR+Uf6nV1HdXpZlM9OZUh4h13 L7Xw== 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=RYaTSFz5DM3c+xWRtK9u0uWhI5NF9uy2TtCzLCwP0SU=; b=bEchMqiIQPtUzdBLH9udg1iJ7gezBOpdyz0pFBOdko0WdiFGbS6f7DRxDAhXAyDBNM wVNMBIkeWPc64BsHT87wihQqbjilPW/yW1XeQ3oMq6viI0HPFaCPDWf2UWbXwIXRMmXT 4OxQSfg1Lup0/5WFheemhSVo3vMZBGfBOEZWK2AWSXTvjBb6ntTdCjVX4atXrMcZsbdu J7cz8es3yi/TcCNfe4oMMQkyIEMgWjnUKIKTkzxES+wFgJwWQlu5cqN4eyowLp3+KKsr j9rzd/JA6uKmI6RsjB1kxHVdj8DdvYRAO3W4R2GAfG3kx85QE32UZKeBqa+ODysfqF1G 3s5w== X-Gm-Message-State: AD7BkJK6EYg5dRs0LkWorv9UeebUIH5vuEmAs+n6kLNKgHJFsfWcLp8dFP4VZCnaAQvOfg== X-Received: by 10.66.175.110 with SMTP id bz14mr67246164pac.41.1459909697009; Tue, 05 Apr 2016 19:28:17 -0700 (PDT) Received: from localhost.localdomain (wsip-70-184-93-199.ph.ph.cox.net. [70.184.93.199]) by smtp.googlemail.com with ESMTPSA id l14sm528682pfi.23.2016.04.05.19.28.15 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 05 Apr 2016 19:28:16 -0700 (PDT) From: Troy Kisky To: netdev@vger.kernel.org, davem@davemloft.net, fugang.duan@nxp.com, lznuaa@gmail.com Subject: [PATCH net-next V3 05/16] net: fec: reduce interrupts Date: Tue, 5 Apr 2016 19:25:51 -0700 Message-Id: <1459909562-22865-6-git-send-email-troy.kisky@boundarydevices.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1459909562-22865-1-git-send-email-troy.kisky@boundarydevices.com> References: <1459909562-22865-1-git-send-email-troy.kisky@boundarydevices.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160405_192837_961099_E2124311 X-CRM114-Status: GOOD ( 17.79 ) 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: andrew@lunn.ch, stillcompiling@gmail.com, arnd@arndb.de, sergei.shtylyov@cogentembedded.com, Troy Kisky , gerg@uclinux.org, fabio.estevam@nxp.com, johannes@sipsolutions.net, l.stach@pengutronix.de, linux-arm-kernel@lists.infradead.org, tremyfr@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=-5.1 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 By clearing the NAPI interrupts in the NAPI routine and not in the interrupt handler, we can reduce the number of interrupts. We also don't need any status variables as the registers are still valid. Also, notice that if budget pkts are received, the next call to fec_enet_rx_napi will now continue to receive the previously pending packets. To test that this actually reduces interrupts, try this command before/after patch cat /proc/interrupts |grep ether; \ ping -s2800 192.168.0.201 -f -c1000 ; \ cat /proc/interrupts |grep ether For me, before this patch is 2996 interrupts. After patch is 2010 interrupts. Signed-off-by: Troy Kisky --- v3: Fix introduced bug of checking for FEC_ENET_TS_TIMER before calling fec_ptp_check_pps_event Changed commit message to show measured changes. Used netdev_info instead of pr_info. Fugang Duan suggested splitting TX and RX into two NAPI contexts, but that should be a separate patch as it is unrelated to what this patch does. --- drivers/net/ethernet/freescale/fec.h | 6 +- drivers/net/ethernet/freescale/fec_main.c | 118 +++++++++++------------------- 2 files changed, 45 insertions(+), 79 deletions(-) diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 6dd0ba8..9d5bdc6 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -505,11 +505,7 @@ struct fec_enet_private { unsigned int total_tx_ring_size; unsigned int total_rx_ring_size; - - unsigned long work_tx; - unsigned long work_rx; - unsigned long work_ts; - unsigned long work_mdio; + uint events; struct platform_device *pdev; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index b4d46f8..918ac82 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -70,8 +70,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); #define DRIVER_NAME "fec" -#define FEC_ENET_GET_QUQUE(_x) ((_x == 0) ? 1 : ((_x == 1) ? 2 : 0)) - /* Pause frame feild and FIFO threshold */ #define FEC_ENET_FCE (1 << 5) #define FEC_ENET_RSEM_V 0x84 @@ -1257,21 +1255,6 @@ static void fec_txq(struct net_device *ndev, struct fec_enet_priv_tx_q *txq) writel(0, txq->bd.reg_desc_active); } -static void -fec_enet_tx(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_enet_priv_tx_q *txq; - u16 queue_id; - /* First process class A queue, then Class B and Best Effort queue */ - for_each_set_bit(queue_id, &fep->work_tx, FEC_ENET_MAX_TX_QS) { - clear_bit(queue_id, &fep->work_tx); - txq = fep->tx_queue[FEC_ENET_GET_QUQUE(queue_id)]; - fec_txq(ndev, txq); - } - return; -} - static int fec_enet_new_rxbdp(struct net_device *ndev, struct bufdesc *bdp, struct sk_buff *skb) { @@ -1505,70 +1488,34 @@ rx_processing_done: return pkt_received; } -static int -fec_enet_rx(struct net_device *ndev, int budget) -{ - int pkt_received = 0; - u16 queue_id; - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_enet_priv_rx_q *rxq; - - for_each_set_bit(queue_id, &fep->work_rx, FEC_ENET_MAX_RX_QS) { - clear_bit(queue_id, &fep->work_rx); - rxq = fep->rx_queue[FEC_ENET_GET_QUQUE(queue_id)]; - pkt_received += fec_rxq(ndev, rxq, budget - pkt_received); - } - return pkt_received; -} - -static bool -fec_enet_collect_events(struct fec_enet_private *fep, uint int_events) -{ - if (int_events == 0) - return false; - - if (int_events & FEC_ENET_RXF_0) - fep->work_rx |= (1 << 2); - if (int_events & FEC_ENET_RXF_1) - fep->work_rx |= (1 << 0); - if (int_events & FEC_ENET_RXF_2) - fep->work_rx |= (1 << 1); - - if (int_events & FEC_ENET_TXF_0) - fep->work_tx |= (1 << 2); - if (int_events & FEC_ENET_TXF_1) - fep->work_tx |= (1 << 0); - if (int_events & FEC_ENET_TXF_2) - fep->work_tx |= (1 << 1); - - return true; -} - static irqreturn_t fec_enet_interrupt(int irq, void *dev_id) { struct net_device *ndev = dev_id; struct fec_enet_private *fep = netdev_priv(ndev); - uint int_events; irqreturn_t ret = IRQ_NONE; + uint eir = readl(fep->hwp + FEC_IEVENT); + uint int_events = eir & readl(fep->hwp + FEC_IMASK); - int_events = readl(fep->hwp + FEC_IEVENT); - writel(int_events, fep->hwp + FEC_IEVENT); - fec_enet_collect_events(fep, int_events); - - if ((fep->work_tx || fep->work_rx) && fep->link) { - ret = IRQ_HANDLED; - + if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) { if (napi_schedule_prep(&fep->napi)) { /* Disable the NAPI interrupts */ writel(FEC_NAPI_IMASK, fep->hwp + FEC_IMASK); __napi_schedule(&fep->napi); + int_events &= ~(FEC_ENET_RXF | FEC_ENET_TXF); + ret = IRQ_HANDLED; + } else { + fep->events |= int_events; + netdev_info(ndev, "couldn't schedule NAPI\n"); } } - if (int_events & FEC_ENET_MII) { + if (int_events) { ret = IRQ_HANDLED; - complete(&fep->mdio_done); + writel(int_events, fep->hwp + FEC_IEVENT); + if (int_events & FEC_ENET_MII) { + complete(&fep->mdio_done); + } } if (fep->ptp_clock) @@ -1581,16 +1528,39 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget) { struct net_device *ndev = napi->dev; struct fec_enet_private *fep = netdev_priv(ndev); - int pkts; - - pkts = fec_enet_rx(ndev, budget); + int pkts = 0; + uint events; - fec_enet_tx(ndev); + do { + events = readl(fep->hwp + FEC_IEVENT); + if (fep->events) { + events |= fep->events; + fep->events = 0; + } + events &= FEC_ENET_RXF | FEC_ENET_TXF; + if (!events) { + if (budget) { + napi_complete(napi); + writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); + } + return pkts; + } - if (pkts < budget) { - napi_complete(napi); - writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); - } + writel(events, fep->hwp + FEC_IEVENT); + if (events & FEC_ENET_RXF_1) + pkts += fec_rxq(ndev, fep->rx_queue[1], budget - pkts); + if (events & FEC_ENET_RXF_2) + pkts += fec_rxq(ndev, fep->rx_queue[2], budget - pkts); + if (events & FEC_ENET_RXF_0) + pkts += fec_rxq(ndev, fep->rx_queue[0], budget - pkts); + if (events & FEC_ENET_TXF_1) + fec_txq(ndev, fep->tx_queue[1]); + if (events & FEC_ENET_TXF_2) + fec_txq(ndev, fep->tx_queue[2]); + if (events & FEC_ENET_TXF_0) + fec_txq(ndev, fep->tx_queue[0]); + } while (pkts < budget); + fep->events |= events & FEC_ENET_RXF; /* save for next callback */ return pkts; }