From patchwork Sat Nov 28 03:22:31 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iyappan Subramanian X-Patchwork-Id: 7716161 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 1787FBEEE1 for ; Sat, 28 Nov 2015 03:24:19 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id EC41E20609 for ; Sat, 28 Nov 2015 03:24:17 +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 E5318205FC for ; Sat, 28 Nov 2015 03:24:16 +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 1a2W4l-000098-Vc; Sat, 28 Nov 2015 03:21:27 +0000 Received: from mail-pa0-x22a.google.com ([2607:f8b0:400e:c03::22a]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1a2W4i-00007k-1E for linux-arm-kernel@lists.infradead.org; Sat, 28 Nov 2015 03:21:24 +0000 Received: by padhx2 with SMTP id hx2so128674402pad.1 for ; Fri, 27 Nov 2015 19:21:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=apm.com; s=apm; h=from:to:cc:subject:date:message-id; bh=qG7Q3wgCdYUTDL+quDTScKmzqfJYemBbwNzxjnSTBsg=; b=oY1Auuf+Pp7GgMgyb5FxE1FchJVeuPkI2O/CrwBxQ5+8N2zEcXLy4ahNBPUOcx0YRY nr/tXnDfrfN1Kv8Q7wYz9S0ROQKVN30d7erz2Jjbd5jUbnvngTc50oYBWEnEmiokXBa+ O6Vl8iUPIc0QD3o9zCJFi26t7VxXtWaqPfX5k= 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; bh=qG7Q3wgCdYUTDL+quDTScKmzqfJYemBbwNzxjnSTBsg=; b=k6qsf84/3xoCgmVUJoOGZQslmhSkVGYdAJiroGNr9WMR0eCUCZwEH736fbzRmkIXB/ vDHeNqovTkFOCigO4kVkTiL2imwsOWCjFxBegaElJdlh1lwDkrvy8bGj3pNr1R1Zpl9M avb/eRyQt7RZ2QnY3kXROUYZVLGy4hBBfdUu9X5yaCQtuUR/6p3WFlaY5k30Gtu00e2K AkzSkl8hOXxpg2TKjyRgqSkPJTM65gzCuCtwyFFCTabKs/TFfmgTM43/YFqVwDA8ZnRd iM0Ld4SFKRhmU3CKvX+93EdtlFjF26sJ52/qHOHao/gM+OHKylijo1blQ1dEPbNJ+i0G eWlg== X-Gm-Message-State: ALoCoQnFEmXGH9CMKZcsLzTxJRIG9htC+FfH+qm1UVUqqVXbz7JFvdevYvXjlyYAnrVGIK3/9uSY X-Received: by 10.98.11.29 with SMTP id t29mr53081008pfi.97.1448680862213; Fri, 27 Nov 2015 19:21:02 -0800 (PST) Received: from isubrama-dev.amcc.com (70-35-53-82.static.wiline.com. [70.35.53.82]) by smtp.gmail.com with ESMTPSA id c1sm37283871pas.1.2015.11.27.19.21.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 27 Nov 2015 19:21:00 -0800 (PST) From: Iyappan Subramanian To: davem@davemloft.net, netdev@vger.kernel.org Subject: [PATCH] drivers: net: xgene: fix Tx flow control Date: Fri, 27 Nov 2015 19:22:31 -0800 Message-Id: <1448680951-4730-1-git-send-email-isubramanian@apm.com> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151127_192124_142661_2218B16E X-CRM114-Status: GOOD ( 15.50 ) X-Spam-Score: -2.7 (--) 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: kdinh@apm.com, patches@apm.com, linux-arm-kernel@lists.infradead.org, Iyappan Subramanian 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.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, 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 Currently the Tx flow control is based on reading the hardware state, which is not accurate since it may not reflect the descriptors that are not yet reached the memory. To accurately control the Tx flow, changing it to be software based. Signed-off-by: Iyappan Subramanian Tested-by: Khuong Dinh --- drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 35 +++++++++++++----------- drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 3 +- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c index 1adfe70..a25cc6f7 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c @@ -289,6 +289,7 @@ static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring, struct sk_buff *skb) { struct device *dev = ndev_to_dev(tx_ring->ndev); + struct xgene_enet_pdata *pdata = netdev_priv(tx_ring->ndev); struct xgene_enet_raw_desc *raw_desc; __le64 *exp_desc = NULL, *exp_bufs = NULL; dma_addr_t dma_addr, pbuf_addr, *frag_dma_addr; @@ -419,6 +420,7 @@ out: raw_desc->m0 = cpu_to_le64(SET_VAL(LL, ll) | SET_VAL(NV, nv) | SET_VAL(USERINFO, tx_ring->tail)); tx_ring->cp_ring->cp_skb[tx_ring->tail] = skb; + atomic_add(count, &pdata->level); tx_ring->tail = tail; return count; @@ -429,14 +431,9 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb, { struct xgene_enet_pdata *pdata = netdev_priv(ndev); struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring; - struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring; - u32 tx_level, cq_level; int count; - tx_level = pdata->ring_ops->len(tx_ring); - cq_level = pdata->ring_ops->len(cp_ring); - if (unlikely(tx_level > pdata->tx_qcnt_hi || - cq_level > pdata->cp_qcnt_hi)) { + if (atomic_read(&pdata->level) > pdata->tx_qcnt_hi) { netif_stop_queue(ndev); return NETDEV_TX_BUSY; } @@ -539,10 +536,13 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, struct xgene_enet_raw_desc *raw_desc, *exp_desc; u16 head = ring->head; u16 slots = ring->slots - 1; - int ret, count = 0, processed = 0; + int ret, count = 0, desc_count = 0, processed = 0; + bool is_completion; do { raw_desc = &ring->raw_desc[head]; + desc_count = 0; + is_completion = false; exp_desc = NULL; if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc))) break; @@ -559,18 +559,24 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, } dma_rmb(); count++; + desc_count++; } - if (is_rx_desc(raw_desc)) + if (is_rx_desc(raw_desc)) { ret = xgene_enet_rx_frame(ring, raw_desc); - else + } else { ret = xgene_enet_tx_completion(ring, raw_desc); + is_completion = true; + } xgene_enet_mark_desc_slot_empty(raw_desc); if (exp_desc) xgene_enet_mark_desc_slot_empty(exp_desc); head = (head + 1) & slots; count++; + desc_count++; processed++; + if (is_completion) + atomic_sub(desc_count, &pdata->level); if (ret) break; @@ -580,10 +586,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, pdata->ring_ops->wr_cmd(ring, -count); ring->head = head; - if (netif_queue_stopped(ring->ndev)) { - if (pdata->ring_ops->len(ring) < pdata->cp_qcnt_low) - netif_wake_queue(ring->ndev); - } + if (netif_queue_stopped(ring->ndev)) + netif_start_queue(ring->ndev); } return processed; @@ -685,6 +689,7 @@ static int xgene_enet_open(struct net_device *ndev) struct xgene_mac_ops *mac_ops = pdata->mac_ops; int ret; + atomic_set(&pdata->level, 0); mac_ops->tx_enable(pdata); mac_ops->rx_enable(pdata); @@ -1033,9 +1038,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev) pdata->tx_ring->cp_ring = cp_ring; pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring); - pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2; - pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2; - pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2; + pdata->tx_qcnt_hi = pdata->tx_ring->slots - 128; return 0; diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h index a6e56b8..4399fa5 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h @@ -155,11 +155,10 @@ struct xgene_enet_pdata { enum xgene_enet_id enet_id; struct xgene_enet_desc_ring *tx_ring; struct xgene_enet_desc_ring *rx_ring; + atomic_t level; char *dev_name; u32 rx_buff_cnt; u32 tx_qcnt_hi; - u32 cp_qcnt_hi; - u32 cp_qcnt_low; u32 rx_irq; u32 txc_irq; u8 cq_cnt;