From patchwork Tue Nov 29 15:00:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Khoronzhuk X-Patchwork-Id: 9452331 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 85B696071C for ; Tue, 29 Nov 2016 15:02:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 79DB41FEC1 for ; Tue, 29 Nov 2016 15:02:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6EC8828384; Tue, 29 Nov 2016 15:02:16 +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=ham 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 914F21FEC1 for ; Tue, 29 Nov 2016 15:02:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933389AbcK2PBy (ORCPT ); Tue, 29 Nov 2016 10:01:54 -0500 Received: from mail-lf0-f52.google.com ([209.85.215.52]:32851 "EHLO mail-lf0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934001AbcK2PBe (ORCPT ); Tue, 29 Nov 2016 10:01:34 -0500 Received: by mail-lf0-f52.google.com with SMTP id c13so123488516lfg.0 for ; Tue, 29 Nov 2016 07:01:33 -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:in-reply-to:references; bh=UZgvMctXKiBdalnjxFynNFVfQvqwYtUn97pXd2hiXpg=; b=SbZTqvccDxCNeSp9zLlDhpdgBkfghtwXgm1OEvjuQd4PxrrbvD2az71/SQ/s6Cy+M2 EfeuI44ppwtNmQu+RGLPrC3skDEhYsvQg7VD3VcgdqfYmtgjgo9FtGt+w6esv/Z7/Grx FtcbAhz3MSsq9LIPv3h7qIXk0fzOXJFlPkcok= 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=UZgvMctXKiBdalnjxFynNFVfQvqwYtUn97pXd2hiXpg=; b=Wx4hA94tYSiOucXtd41WMg4PC+mOjpZ8VOi92QwPb4hC+anC4QZXQagfnobOLulL/O qww8ujCldJA/txLfq1Qyclzggkc7Ge2C4quZAKaEhDtudCrA6cEio3CN3MWbM6EeIOkT Y+Wx4mzZ3AQYbBoiv/QMn5ZVLQzmmjPtakFOckQ8PWYy/GOop9hNq3TEeo3yy2oCIRyi JqZnvAw0uhz9Ysr2eGFsmrziAjexBnHIuRwDHNe/UE4yHw6NORsnl8CSaomqa6Lpw4/b X9ZFxZ/7k6BGQPllAgven6kWdIeQ6x/sVrTw4wpAIED3atWJfqp1l65e8cfiIHT+gkar IA8w== X-Gm-Message-State: AKaTC00T2KLqrHYir21P30cPGXBZM5bcXlh5oL0yWRdW9NRQyybye9Mz/bVRVDCB9xgKvF4O X-Received: by 10.25.89.137 with SMTP id n131mr8758372lfb.75.1480431682636; Tue, 29 Nov 2016 07:01:22 -0800 (PST) Received: from localhost.localdomain (183-224-132-95.pool.ukrtel.net. [95.132.224.183]) by smtp.gmail.com with ESMTPSA id c78sm9663673lfc.39.2016.11.29.07.01.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 29 Nov 2016 07:01:22 -0800 (PST) From: Ivan Khoronzhuk To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, mugunthanvnm@ti.com, grygorii.strashko@ti.com Cc: linux-omap@vger.kernel.org, Ivan Khoronzhuk Subject: [PATCH 3/5] net: ethernet: ti: cpsw: add .ndo to set per-queue rate Date: Tue, 29 Nov 2016 17:00:49 +0200 Message-Id: <1480431651-6081-4-git-send-email-ivan.khoronzhuk@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1480431651-6081-1-git-send-email-ivan.khoronzhuk@linaro.org> References: <1480431651-6081-1-git-send-email-ivan.khoronzhuk@linaro.org> 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 This patch allows to rate limit queues tx queues for cpsw interface. The rate is set in absolute Mb/s units and cannot be more a speed an interface is connected with. The rate for a tx queue can be tested with: ethtool -L eth0 rx 4 tx 4 echo 100 > /sys/class/net/eth0/queues/tx-0/tx_maxrate echo 200 > /sys/class/net/eth0/queues/tx-1/tx_maxrate echo 50 > /sys/class/net/eth0/queues/tx-2/tx_maxrate echo 30 > /sys/class/net/eth0/queues/tx-3/tx_maxrate tc qdisc add dev eth0 root handle 1: multiq tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip\ dport 5001 0xffff action skbedit queue_mapping 0 tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip\ dport 5002 0xffff action skbedit queue_mapping 1 tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip\ dport 5003 0xffff action skbedit queue_mapping 2 tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip\ dport 5004 0xffff action skbedit queue_mapping 3 iperf -c 192.168.2.1 -b 110M -p 5001 -f m -t 60 iperf -c 192.168.2.1 -b 215M -p 5002 -f m -t 60 iperf -c 192.168.2.1 -b 55M -p 5003 -f m -t 60 iperf -c 192.168.2.1 -b 32M -p 5004 -f m -t 60 Signed-off-by: Ivan Khoronzhuk --- drivers/net/ethernet/ti/cpsw.c | 87 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index da40ea5..c102675 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -1872,6 +1872,88 @@ static int cpsw_ndo_vlan_rx_kill_vid(struct net_device *ndev, return ret; } +static int cpsw_ndo_set_tx_maxrate(struct net_device *ndev, int queue, u32 rate) +{ + struct cpsw_priv *priv = netdev_priv(ndev); + int tx_ch_num = ndev->real_num_tx_queues; + u32 consumed_rate, min_rate, max_rate; + struct cpsw_common *cpsw = priv->cpsw; + struct cpsw_slave *slave; + int ret, i, weight; + int rlim_num = 0; + u32 ch_rate; + + ch_rate = netdev_get_tx_queue(ndev, queue)->tx_maxrate; + if (ch_rate == rate) + return 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; + + consumed_rate = 0; + for (i = 0; i < tx_ch_num; i++) { + if (i == queue) + ch_rate = rate; + else + ch_rate = netdev_get_tx_queue(ndev, i)->tx_maxrate; + + if (!ch_rate) + continue; + + rlim_num++; + consumed_rate += ch_rate; + } + + if (consumed_rate > max_rate) + dev_info(priv->dev, "The common rate shouldn't be more than %dMbps", + max_rate); + + if (consumed_rate > max_rate) { + if (max_rate == 10 && consumed_rate <= 100) { + max_rate = 100; + } else if (max_rate <= 100 && consumed_rate <= 1000) { + max_rate = 1000; + } else { + dev_err(priv->dev, "The common rate cannot be more than %dMbps", + max_rate); + return -EINVAL; + } + } + + if (consumed_rate > max_rate) { + dev_err(priv->dev, "The common rate cannot be more than %dMbps", + max_rate); + return -EINVAL; + } + + rate *= 1000; + min_rate = cpdma_chan_get_min_rate(cpsw->dma); + if ((rate < min_rate && rate)) { + dev_err(priv->dev, "The common rate cannot be less than %dMbps", + min_rate); + return -EINVAL; + } + + ret = pm_runtime_get_sync(cpsw->dev); + if (ret < 0) { + pm_runtime_put_noidle(cpsw->dev); + return ret; + } + + if (rlim_num == tx_ch_num) + max_rate = consumed_rate; + + weight = (rate * 100) / (max_rate * 1000); + cpdma_chan_set_weight(cpsw->txch[queue], weight); + + ret = cpdma_chan_set_rate(cpsw->txch[queue], rate); + pm_runtime_put(cpsw->dev); + return ret; +} + static const struct net_device_ops cpsw_netdev_ops = { .ndo_open = cpsw_ndo_open, .ndo_stop = cpsw_ndo_stop, @@ -1881,6 +1963,7 @@ static const struct net_device_ops cpsw_netdev_ops = { .ndo_validate_addr = eth_validate_addr, .ndo_tx_timeout = cpsw_ndo_tx_timeout, .ndo_set_rx_mode = cpsw_ndo_set_rx_mode, + .ndo_set_tx_maxrate = cpsw_ndo_set_tx_maxrate, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = cpsw_ndo_poll_controller, #endif @@ -2100,6 +2183,7 @@ static int cpsw_update_channels_res(struct cpsw_priv *priv, int ch_num, int rx) int (*poll)(struct napi_struct *, int); struct cpsw_common *cpsw = priv->cpsw; void (*handler)(void *, int, int); + struct netdev_queue *queue; struct cpdma_chan **chan; int ret, *ch; @@ -2117,6 +2201,8 @@ static int cpsw_update_channels_res(struct cpsw_priv *priv, int ch_num, int rx) while (*ch < ch_num) { chan[*ch] = cpdma_chan_create(cpsw->dma, *ch, handler, rx); + queue = netdev_get_tx_queue(priv->ndev, *ch); + queue->tx_maxrate = 0; if (IS_ERR(chan[*ch])) return PTR_ERR(chan[*ch]); @@ -2752,6 +2838,7 @@ static int cpsw_probe(struct platform_device *pdev) dma_params.desc_align = 16; dma_params.has_ext_regs = true; dma_params.desc_hw_addr = dma_params.desc_mem_phys; + dma_params.bus_freq_mhz = cpsw->bus_freq_mhz; cpsw->dma = cpdma_ctlr_create(&dma_params); if (!cpsw->dma) {