From patchwork Tue Dec 6 01:45:00 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 9461861 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 7A9C560231 for ; Tue, 6 Dec 2016 01:45:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 667232815E for ; Tue, 6 Dec 2016 01:45:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 58D952817F; Tue, 6 Dec 2016 01:45:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D56052815E for ; Tue, 6 Dec 2016 01:45:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751244AbcLFBpJ (ORCPT ); Mon, 5 Dec 2016 20:45:09 -0500 Received: from mail-lf0-f42.google.com ([209.85.215.42]:33227 "EHLO mail-lf0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751581AbcLFBpH (ORCPT ); Mon, 5 Dec 2016 20:45:07 -0500 Received: by mail-lf0-f42.google.com with SMTP id c13so234877043lfg.0 for ; Mon, 05 Dec 2016 17:45:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=26GBwByV40ThHTNrKvjm33XkBUlCXA2EQ6yVSuusuM8=; b=OS5wNnL1yTvFZOeqPUjbhifI2hFKdmXBaPaYSbpdoCS6CXFL3d/W2tSD+fjKVoYNu3 IF2eWmYdmgiRUNcoXIWJzL9ZQO7pP+J+IWTB20U8BHzIVLbMfxZIS1sF30LGnj2k6NOE wCT2zHn8Ulpb0M75amQ6nTxM2XiI5b9U/Sy1Y= 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=26GBwByV40ThHTNrKvjm33XkBUlCXA2EQ6yVSuusuM8=; b=e6rCEEq0mZ4imCmr9qDsLJPmceqT0f/76onhKWzNdgnA15Qb6Y55q2eSjSJZ22e+5O 1CAjffNDPzd28Dy1js1feS6eVPi2k+tMuSVXAV0HuyS3qi1pFoYdHMjswXTybve6TMou N1NSrlVvEk6ITmfiaGNR5Wctzg1gxQU0B+331TtFPBa9H8GPf+Ic+/y9ggUrVqOHg567 NbC7RCKIZgbC60GHKEglwV6C5y+Wowwu8QQqLHPSX6GWU/huZd/z8C9eEC8yTiWGhL/F G85r4UbErAoLXn9IvByV1Xf7/rG4WDJ886QJ7Krivvp2mgOxvk/y6RwUDDchWd+XMLjD L26g== X-Gm-Message-State: AKaTC01UPnxSc23DlML/bJoZywJUvE2EizN9LKW6U1etlO8bIaq1F1Zw1WjLYWy+8j4A6dSo X-Received: by 10.46.72.1 with SMTP id v1mr20764702lja.49.1480988705252; Mon, 05 Dec 2016 17:45:05 -0800 (PST) Received: from localhost.localdomain (183-224-132-95.pool.ukrtel.net. [95.132.224.183]) by smtp.gmail.com with ESMTPSA id r21sm3498885lff.17.2016.12.05.17.45.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 05 Dec 2016 17:45:03 -0800 (PST) From: Ivan Khoronzhuk To: mugunthanvnm@ti.com, grygorii.strashko@ti.com Cc: linux-omap@vger.kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Ivan Khoronzhuk Subject: [PATCH] net: ethernet: ti: cpsw: fix early budget split Date: Tue, 6 Dec 2016 03:45:00 +0200 Message-Id: <1480988700-17046-1-git-send-email-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.7.4 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The budget split function requires the phy speed to be known. While ndo open a phy speed identification is postponed till the moment link is up. Hence, move it to appropriate callback, when link is up. Reported-by: Grygorii Strashko Fixes: 8feb0a196507 ("net: ethernet: ti: cpsw: split tx budget according between channels") Signed-off-by: Ivan Khoronzhuk --- Based on net-next/master drivers/net/ethernet/ti/cpsw.c | 154 ++++++++++++++++++++--------------------- 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 3f96c57..f373a4b 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -753,6 +753,82 @@ static void cpsw_rx_handler(void *token, int len, int status) dev_kfree_skb_any(new_skb); } +/* split budget depending on channel rates */ +static void cpsw_split_budget(struct net_device *ndev) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + struct cpsw_common *cpsw = priv->cpsw; + struct cpsw_vector *txv = cpsw->txv; + u32 consumed_rate, bigest_rate = 0; + int budget, bigest_rate_ch = 0; + struct cpsw_slave *slave; + int i, rlim_ch_num = 0; + u32 ch_rate, max_rate; + int ch_budget = 0; + + if (cpsw->data.dual_emac) + slave = &cpsw->slaves[priv->emac_port]; + else + slave = &cpsw->slaves[cpsw->data.active_slave]; + + max_rate = slave->phy->speed * 1000; + + consumed_rate = 0; + for (i = 0; i < cpsw->tx_ch_num; i++) { + ch_rate = cpdma_chan_get_rate(txv[i].ch); + if (!ch_rate) + continue; + + rlim_ch_num++; + consumed_rate += ch_rate; + } + + if (cpsw->tx_ch_num == rlim_ch_num) { + max_rate = consumed_rate; + } else { + ch_budget = (consumed_rate * CPSW_POLL_WEIGHT) / max_rate; + ch_budget = (CPSW_POLL_WEIGHT - ch_budget) / + (cpsw->tx_ch_num - rlim_ch_num); + bigest_rate = (max_rate - consumed_rate) / + (cpsw->tx_ch_num - rlim_ch_num); + } + + /* split tx budget */ + budget = CPSW_POLL_WEIGHT; + for (i = 0; i < cpsw->tx_ch_num; i++) { + ch_rate = cpdma_chan_get_rate(txv[i].ch); + if (ch_rate) { + txv[i].budget = (ch_rate * CPSW_POLL_WEIGHT) / max_rate; + if (!txv[i].budget) + txv[i].budget = 1; + if (ch_rate > bigest_rate) { + bigest_rate_ch = i; + bigest_rate = ch_rate; + } + } else { + txv[i].budget = ch_budget; + if (!bigest_rate_ch) + bigest_rate_ch = i; + } + + budget -= txv[i].budget; + } + + if (budget) + txv[bigest_rate_ch].budget += budget; + + /* split rx budget */ + budget = CPSW_POLL_WEIGHT; + ch_budget = budget / cpsw->rx_ch_num; + for (i = 0; i < cpsw->rx_ch_num; i++) { + cpsw->rxv[i].budget = ch_budget; + budget -= ch_budget; + } + + if (budget) + cpsw->rxv[0].budget += budget; +} + static irqreturn_t cpsw_tx_interrupt(int irq, void *dev_id) { struct cpsw_common *cpsw = dev_id; @@ -941,6 +1017,7 @@ static void cpsw_adjust_link(struct net_device *ndev) for_each_slave(priv, _cpsw_adjust_link, priv, &link); if (link) { + cpsw_split_budget(priv->ndev); netif_carrier_on(ndev); if (netif_running(ndev)) netif_tx_wake_all_queues(ndev); @@ -1280,82 +1357,6 @@ static void cpsw_init_host_port(struct cpsw_priv *priv) } } -/* split budget depending on channel rates */ -static void cpsw_split_budget(struct net_device *ndev) -{ - struct cpsw_priv *priv = netdev_priv(ndev); - struct cpsw_common *cpsw = priv->cpsw; - struct cpsw_vector *txv = cpsw->txv; - u32 consumed_rate, bigest_rate = 0; - int budget, bigest_rate_ch = 0; - struct cpsw_slave *slave; - int i, rlim_ch_num = 0; - u32 ch_rate, max_rate; - int ch_budget = 0; - - if (cpsw->data.dual_emac) - slave = &cpsw->slaves[priv->emac_port]; - else - slave = &cpsw->slaves[cpsw->data.active_slave]; - - max_rate = slave->phy->speed * 1000; - - consumed_rate = 0; - for (i = 0; i < cpsw->tx_ch_num; i++) { - ch_rate = cpdma_chan_get_rate(txv[i].ch); - if (!ch_rate) - continue; - - rlim_ch_num++; - consumed_rate += ch_rate; - } - - if (cpsw->tx_ch_num == rlim_ch_num) { - max_rate = consumed_rate; - } else { - ch_budget = (consumed_rate * CPSW_POLL_WEIGHT) / max_rate; - ch_budget = (CPSW_POLL_WEIGHT - ch_budget) / - (cpsw->tx_ch_num - rlim_ch_num); - bigest_rate = (max_rate - consumed_rate) / - (cpsw->tx_ch_num - rlim_ch_num); - } - - /* split tx budget */ - budget = CPSW_POLL_WEIGHT; - for (i = 0; i < cpsw->tx_ch_num; i++) { - ch_rate = cpdma_chan_get_rate(txv[i].ch); - if (ch_rate) { - txv[i].budget = (ch_rate * CPSW_POLL_WEIGHT) / max_rate; - if (!txv[i].budget) - txv[i].budget = 1; - if (ch_rate > bigest_rate) { - bigest_rate_ch = i; - bigest_rate = ch_rate; - } - } else { - txv[i].budget = ch_budget; - if (!bigest_rate_ch) - bigest_rate_ch = i; - } - - budget -= txv[i].budget; - } - - if (budget) - txv[bigest_rate_ch].budget += budget; - - /* split rx budget */ - budget = CPSW_POLL_WEIGHT; - ch_budget = budget / cpsw->rx_ch_num; - for (i = 0; i < cpsw->rx_ch_num; i++) { - cpsw->rxv[i].budget = ch_budget; - budget -= ch_budget; - } - - if (budget) - cpsw->rxv[0].budget += budget; -} - static int cpsw_fill_rx_channels(struct cpsw_priv *priv) { struct cpsw_common *cpsw = priv->cpsw; @@ -1501,7 +1502,6 @@ static int cpsw_ndo_open(struct net_device *ndev) cpsw_set_coalesce(ndev, &coal); } - cpsw_split_budget(ndev); cpdma_ctlr_start(cpsw->dma); cpsw_intr_enable(cpsw);