Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp5142681imm; Tue, 12 Jun 2018 03:19:51 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJJprxH7gtJoEa0qM41JKrd/5cT60Fxxl39nPqeU/1gWc1lPMlBz8rp4CjHz22oPTkliHbu X-Received: by 2002:a65:4a10:: with SMTP id s16-v6mr2678107pgq.57.1528798791777; Tue, 12 Jun 2018 03:19:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528798791; cv=none; d=google.com; s=arc-20160816; b=Y8ZHR1sA9KYUsawuW62n7Cg5GeCDc70R5sxyRvz1JfR1M8+3W84bQU0m2PeCZ+EOKl pm2OLJDFk+vCOuQGyJrt61COUbAWnn9T1DBX8/moFXvRXGGqdjqExEnuGT/q+IO/T7rZ SS/twFh0yQ4UY+DPpm0eEBG4eIKuMMsWa1TGCVGhOYcEWvtPzhGz+UGGOisWnEwQ0F5q zDOV2Ct9YxnXnZkIE5yM2r/7dRSh9WxBtEJ7WwH4g8qrOdgAYOOSvyXb1QuDeGkeg3sX 0fQRpVmvt48hhQWtEKa44W1N+DtzeC1BggVMtMy9Z7qyizQ7xWETEaNs2KzdiJWa3Iq3 /G5A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-transfer-encoding:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature :arc-authentication-results; bh=WVngv6YaAAPl6bf5KUTbrNZjrOn1XZT3cINjopZbtxQ=; b=TNvMt/IIpwsw1iqUlGFcqQ9jWYnWFky3sCN/6L/BbfugtchYiWxyRF1WjLbVGzf5kv ++wQCyhJo4LQepO9mzYkNALCbqWyGQHeIbZpQozPFDKiXcWru1BWSZM/TDIPVaL7O1Gr tND1tvKUH8kKMnSa50bXfhfAJBY2BZOFCxotDjMTO3roIuFGRqFR2Hf6DNvzTPonBY45 IN5OBLXqjr55njiff83/59r9vu9oxWMnwq032mTB75Ce5w3Sg6NQRoZhzgQ6ByWRYxDf mt1i7d0EL7G/Wkhn91wUAcQLGONrzliggMtX0LA1HjuS7QCPu5bA/GQXj8M7569NcleK CmnA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CxBSqsBS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w6-v6si476156pgc.276.2018.06.12.03.19.37; Tue, 12 Jun 2018 03:19:51 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=CxBSqsBS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932608AbeFLKTF (ORCPT + 99 others); Tue, 12 Jun 2018 06:19:05 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:41625 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754209AbeFLKTB (ORCPT ); Tue, 12 Jun 2018 06:19:01 -0400 Received: by mail-wr0-f193.google.com with SMTP id h10-v6so23450719wrq.8 for ; Tue, 12 Jun 2018 03:19:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=WVngv6YaAAPl6bf5KUTbrNZjrOn1XZT3cINjopZbtxQ=; b=CxBSqsBS7PBNFkPPTFSkJ2KZdkScqvaSO2QOoHONO755JLloS5b8by5xwNziUzDlSI d8hsXsJXgxMdMtMK7ta5dyBH8A52j76cnUtO5jGvnxW8S8pg1fDgBQBwiiB/undM31pv zpMS78SxmX8NfwReY9RQns5EV/TpQllDH3r7g= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=WVngv6YaAAPl6bf5KUTbrNZjrOn1XZT3cINjopZbtxQ=; b=O41CwtvPexNDnKVqVecRPLBEAnL9HUp3ZIzBDH7dZ6Yuy6RW/jEr9MvC7a1gmgfJQE KYMyAL23uVcCDfjuiH+xCth7UcAeeFhOZiS8Sv5oGXt3aZ5/8nf9t1pLdPnpOVnFnEaj SVKYQxr0LokS0lPvjMnSUhaebMbQID7sdbgibuCDrCEapT0AWuRBAINmnZQDFE7ifMl6 7wQfg+vSTU0cPPaoQTY6OOdwItq9hdCHbNnt3LkwPRyC9YeH8Lizestp+YniIHzvb2aZ Qc8imb4dyEuBBQjIlU+XSnPrYfSWE5FHtWuOTsSLbpO2ZsBtiHwFb24ApJzp6dwJWEf2 cT1Q== X-Gm-Message-State: APt69E1+Fbp+LXB8OI6oo1fg0TUdnRrqS4o15Jqh6bvcweXAsFUZbabx 9HZNe8dyLHjqotOHaPGQ8k1T4w== X-Received: by 2002:adf:98cf:: with SMTP id w73-v6mr2282763wrb.209.1528798740493; Tue, 12 Jun 2018 03:19:00 -0700 (PDT) Received: from apalos ([2a02:587:4609:4e00:90f6:c9f4:adc1:1abe]) by smtp.gmail.com with ESMTPSA id b204-v6sm120181wmh.22.2018.06.12.03.18.58 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 12 Jun 2018 03:18:59 -0700 (PDT) Date: Tue, 12 Jun 2018 13:18:56 +0300 From: Ilias Apalodimas To: Ivan Khoronzhuk Cc: grygorii.strashko@ti.com, davem@davemloft.net, corbet@lwn.net, akpm@linux-foundation.org, netdev@vger.kernel.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-omap@vger.kernel.org, vinicius.gomes@intel.com, henrik@austad.us, jesus.sanchez-palencia@intel.com, p-varis@ti.com, spatton@ti.com, francois.ozog@linaro.org, yogeshs@ti.com, nsekhar@ti.com Subject: Re: [PATCH net-next 4/6] net: ethernet: ti: cpsw: add CBS Qdisc offload Message-ID: <20180612101856.GA29936@apalos> References: <20180611133047.4818-1-ivan.khoronzhuk@linaro.org> <20180611133047.4818-5-ivan.khoronzhuk@linaro.org> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20180611133047.4818-5-ivan.khoronzhuk@linaro.org> User-Agent: Mutt/1.5.24 (2015-08-30) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Jun 11, 2018 at 04:30:45PM +0300, Ivan Khoronzhuk wrote: > The cpsw has up to 4 FIFOs per port and upper 3 FIFOs can feed rate > limited queue with shaping. In order to set and enable shaping for > those 3 FIFOs queues the network device with CBS qdisc attached is > needed. The CBS configuration is added for dual-emac/single port mode > only, but potentially can be used in switch mode also, based on > switchdev for instance. > > Despite the FIFO shapers can work w/o cpdma level shapers the base > usage must be in combine with cpdma level shapers as described in TRM, > that are set as maximum rates for interface queues with sysfs. > > One of the possible configuration with txq shapers and CBS shapers: > > Configured with echo RATE > > /sys/class/net/eth0/queues/tx-0/tx_maxrate > /--------------------------------------------------- > / > / cpdma level shapers > +----+ +----+ +----+ +----+ +----+ +----+ +----+ +----+ > | c7 | | c6 | | c5 | | c4 | | c3 | | c2 | | c1 | | c0 | > \ / \ / \ / \ / \ / \ / \ / \ / > \ / \ / \ / \ / \ / \ / \ / \ / > \/ \/ \/ \/ \/ \/ \/ \/ > +---------|------|------|------|-------------------------------------+ > | +----+ | | +---+ | > | | +----+ | | | > | v v v v | > | +----+ +----+ +----+ +----+ p p+----+ +----+ +----+ +----+ | > | | | | | | | | | o o| | | | | | | | | > | | f3 | | f2 | | f1 | | f0 | r CPSW r| f3 | | f2 | | f1 | | f0 | | > | | | | | | | | | t t| | | | | | | | | > | \ / \ / \ / \ / 0 1\ / \ / \ / \ / | > | \ X \ / \ / \ / \ / \ / \ / \ / | > | \/ \ \/ \/ \/ \/ \/ \/ \/ | > +-------\------------------------------------------------------------+ > \ > \ FIFO shaper, set with CBS offload added in this patch, > \ FIFO0 cannot be rate limited > ------------------------------------------------------ > > CBS shaper configuration is supposed to be used with root MQPRIO Qdisc > offload allowing to add sk_prio->tc->txq maps that direct traffic to > appropriate tx queue and maps L2 priority to FIFO shaper. > > The CBS shaper is intended to be used for AVB where L2 priority > (pcp field) is used to differentiate class of traffic. So additionally > vlan needs to be created with appropriate egress sk_prio->l2 prio map. > > If CBS has several tx queues assigned to it, the sum of their > bandwidth has not overlap bandwidth set for CBS. It's recomended the > CBS bandwidth to be a little bit more. > > The CBS shaper is configured with CBS qdisc offload interface using tc > tool from iproute2 packet. > > For instance: > > $ tc qdisc replace dev eth0 handle 100: parent root mqprio num_tc 3 \ > map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@0 1@1 2@2 hw 1 > > $ tc -g class show dev eth0 > +---(100:ffe2) mqprio > | ???+---(100:3) mqprio > | ???+---(100:4) mqprio > | ??? > +---(100:ffe1) mqprio > | ???+---(100:2) mqprio > | ??? > +---(100:ffe0) mqprio > ????+---(100:1) mqprio > > $ tc qdisc add dev eth0 parent 100:1 cbs locredit -1440 \ > hicredit 60 sendslope -960000 idleslope 40000 offload 1 > > $ tc qdisc add dev eth0 parent 100:2 cbs locredit -1470 \ > hicredit 62 sendslope -980000 idleslope 20000 offload 1 > > The above code set CBS shapers for tc0 and tc1, for that txq0 and > txq1 is used. Pay attention, the real set bandwidth can differ a bit > due to discreteness of configuration parameters. > > Here parameters like locredit, hicredit and sendslope are ignored > internally and are supposed to be set with assumption that maximum > frame size for frame - 1500. > > It's supposed that interface speed is not changed while reconnection, > not always is true, so inform user in case speed of interface was > changed, as it can impact on dependent shapers configuration. > > For more examples see Documentation. > > Signed-off-by: Ivan Khoronzhuk > --- > drivers/net/ethernet/ti/cpsw.c | 221 +++++++++++++++++++++++++++++++++ > 1 file changed, 221 insertions(+) > > diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c > index fd967d2bce5d..87a5586c5ea5 100644 > --- a/drivers/net/ethernet/ti/cpsw.c > +++ b/drivers/net/ethernet/ti/cpsw.c > @@ -46,6 +46,8 @@ > #include "cpts.h" > #include "davinci_cpdma.h" > > +#include > + > #define CPSW_DEBUG (NETIF_MSG_HW | NETIF_MSG_WOL | \ > NETIF_MSG_DRV | NETIF_MSG_LINK | \ > NETIF_MSG_IFUP | NETIF_MSG_INTR | \ > @@ -154,8 +156,12 @@ do { \ > #define IRQ_NUM 2 > #define CPSW_MAX_QUEUES 8 > #define CPSW_CPDMA_DESCS_POOL_SIZE_DEFAULT 256 > +#define CPSW_FIFO_QUEUE_TYPE_SHIFT 16 > +#define CPSW_FIFO_SHAPE_EN_SHIFT 16 > +#define CPSW_FIFO_RATE_EN_SHIFT 20 > #define CPSW_TC_NUM 4 > #define CPSW_FIFO_SHAPERS_NUM (CPSW_TC_NUM - 1) > +#define CPSW_PCT_MASK 0x7f > > #define CPSW_RX_VLAN_ENCAP_HDR_PRIO_SHIFT 29 > #define CPSW_RX_VLAN_ENCAP_HDR_PRIO_MSK GENMASK(2, 0) > @@ -457,6 +463,8 @@ struct cpsw_priv { > bool rx_pause; > bool tx_pause; > bool mqprio_hw; > + int fifo_bw[CPSW_TC_NUM]; > + int shp_cfg_speed; > u32 emac_port; > struct cpsw_common *cpsw; > }; > @@ -1081,6 +1089,38 @@ static void cpsw_set_slave_mac(struct cpsw_slave *slave, > slave_write(slave, mac_lo(priv->mac_addr), SA_LO); > } > > +static bool cpsw_shp_is_off(struct cpsw_priv *priv) > +{ > + struct cpsw_common *cpsw = priv->cpsw; > + struct cpsw_slave *slave; > + u32 shift, mask, val; > + > + val = readl_relaxed(&cpsw->regs->ptype); > + > + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; > + shift = CPSW_FIFO_SHAPE_EN_SHIFT + 3 * slave->slave_num; > + mask = 7 << shift; > + val = val & mask; > + > + return !val; > +} > + > +static void cpsw_fifo_shp_on(struct cpsw_priv *priv, int fifo, int on) > +{ > + struct cpsw_common *cpsw = priv->cpsw; > + struct cpsw_slave *slave; > + u32 shift, mask, val; > + > + val = readl_relaxed(&cpsw->regs->ptype); > + > + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; > + shift = CPSW_FIFO_SHAPE_EN_SHIFT + 3 * slave->slave_num; > + mask = (1 << --fifo) << shift; > + val = on ? val | mask : val & ~mask; > + > + writel_relaxed(val, &cpsw->regs->ptype); > +} > + > static void _cpsw_adjust_link(struct cpsw_slave *slave, > struct cpsw_priv *priv, bool *link) > { > @@ -1120,6 +1160,12 @@ static void _cpsw_adjust_link(struct cpsw_slave *slave, > mac_control |= BIT(4); > > *link = true; > + > + if (priv->shp_cfg_speed && > + priv->shp_cfg_speed != slave->phy->speed && > + !cpsw_shp_is_off(priv)) > + dev_warn(priv->dev, > + "Speed was changed, CBS sahper speeds are changed!"); > } else { > mac_control = 0; > /* disable forwarding */ > @@ -1589,6 +1635,178 @@ static int cpsw_tc_to_fifo(int tc, int num_tc) > return CPSW_FIFO_SHAPERS_NUM - tc; > } > > +static int cpsw_set_fifo_bw(struct cpsw_priv *priv, int fifo, int bw) > +{ > + struct cpsw_common *cpsw = priv->cpsw; > + u32 val = 0, send_pct, shift; > + struct cpsw_slave *slave; > + int pct = 0, i; > + > + if (bw > priv->shp_cfg_speed * 1000) > + goto err; > + > + /* shaping has to stay enabled for highest fifos linearly > + * and fifo bw no more then interface can allow > + */ > + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; > + send_pct = slave_read(slave, SEND_PERCENT); > + for (i = CPSW_FIFO_SHAPERS_NUM; i > 0; i--) { > + if (!bw) { > + if (i >= fifo || !priv->fifo_bw[i]) > + continue; > + > + dev_warn(priv->dev, "Prev FIFO%d is shaped", i); > + continue; > + } > + > + if (!priv->fifo_bw[i] && i > fifo) { > + dev_err(priv->dev, "Upper FIFO%d is not shaped", i); > + return -EINVAL; > + } > + > + shift = (i - 1) * 8; > + if (i == fifo) { > + send_pct &= ~(CPSW_PCT_MASK << shift); > + val = DIV_ROUND_UP(bw, priv->shp_cfg_speed * 10); > + if (!val) > + val = 1; > + > + send_pct |= val << shift; > + pct += val; > + continue; > + } > + > + if (priv->fifo_bw[i]) > + pct += (send_pct >> shift) & CPSW_PCT_MASK; > + } > + > + if (pct >= 100) > + goto err; > + > + slave_write(slave, send_pct, SEND_PERCENT); > + priv->fifo_bw[fifo] = bw; > + > + dev_warn(priv->dev, "set FIFO%d bw = %d\n", fifo, > + DIV_ROUND_CLOSEST(val * priv->shp_cfg_speed, 100)); > + > + return 0; > +err: > + dev_err(priv->dev, "Bandwidth doesn't fit in tc configuration"); > + return -EINVAL; > +} > + > +static int cpsw_set_fifo_rlimit(struct cpsw_priv *priv, int fifo, int bw) > +{ > + struct cpsw_common *cpsw = priv->cpsw; > + struct cpsw_slave *slave; > + u32 tx_in_ctl_rg, val; > + int ret; > + > + ret = cpsw_set_fifo_bw(priv, fifo, bw); > + if (ret) > + return ret; > + > + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; > + tx_in_ctl_rg = cpsw->version == CPSW_VERSION_1 ? > + CPSW1_TX_IN_CTL : CPSW2_TX_IN_CTL; > + > + if (!bw) > + cpsw_fifo_shp_on(priv, fifo, bw); > + > + val = slave_read(slave, tx_in_ctl_rg); > + if (cpsw_shp_is_off(priv)) { > + /* disable FIFOs rate limited queues */ > + val &= ~(0xf << CPSW_FIFO_RATE_EN_SHIFT); > + > + /* set type of FIFO queues to normal priority mode */ > + val &= ~(3 << CPSW_FIFO_QUEUE_TYPE_SHIFT); > + > + /* set type of FIFO queues to be rate limited */ > + if (bw) > + val |= 2 << CPSW_FIFO_QUEUE_TYPE_SHIFT; > + else > + priv->shp_cfg_speed = 0; > + } > + > + /* toggle a FIFO rate limited queue */ > + if (bw) > + val |= BIT(fifo + CPSW_FIFO_RATE_EN_SHIFT); > + else > + val &= ~BIT(fifo + CPSW_FIFO_RATE_EN_SHIFT); > + slave_write(slave, val, tx_in_ctl_rg); > + > + /* FIFO transmit shape enable */ > + cpsw_fifo_shp_on(priv, fifo, bw); > + return 0; > +} > + > +/* Defaults: > + * class A - prio 3 > + * class B - prio 2 > + * shaping for class A should be set first > + */ > +static int cpsw_set_cbs(struct net_device *ndev, > + struct tc_cbs_qopt_offload *qopt) > +{ > + struct cpsw_priv *priv = netdev_priv(ndev); > + struct cpsw_common *cpsw = priv->cpsw; > + struct cpsw_slave *slave; > + int prev_speed = 0; > + int tc, ret, fifo; > + u32 bw = 0; > + > + tc = netdev_txq_to_tc(priv->ndev, qopt->queue); > + > + /* enable channels in backward order, as highest FIFOs must be rate > + * limited first and for compliance with CPDMA rate limited channels > + * that also used in bacward order. FIFO0 cannot be rate limited. > + */ > + fifo = cpsw_tc_to_fifo(tc, ndev->num_tc); > + if (!fifo) { > + dev_err(priv->dev, "Last tc%d can't be rate limited", tc); > + return -EINVAL; > + } > + > + /* do nothing, it's disabled anyway */ > + if (!qopt->enable && !priv->fifo_bw[fifo]) > + return 0; > + > + /* shapers can be set if link speed is known */ > + slave = &cpsw->slaves[cpsw_slave_index(cpsw, priv)]; > + if (slave->phy && slave->phy->link) { > + if (priv->shp_cfg_speed && > + priv->shp_cfg_speed != slave->phy->speed) > + prev_speed = priv->shp_cfg_speed; > + > + priv->shp_cfg_speed = slave->phy->speed; > + } > + > + if (!priv->shp_cfg_speed) { > + dev_err(priv->dev, "Link speed is not known"); > + return -1; > + } > + > + ret = pm_runtime_get_sync(cpsw->dev); > + if (ret < 0) { > + pm_runtime_put_noidle(cpsw->dev); > + return ret; > + } > + > + bw = qopt->enable ? qopt->idleslope : 0; > + ret = cpsw_set_fifo_rlimit(priv, fifo, bw); > + if (ret) { > + priv->shp_cfg_speed = prev_speed; > + prev_speed = 0; > + } > + > + if (bw && prev_speed) > + dev_warn(priv->dev, > + "Speed was changed, CBS sahper speeds are changed!"); > + > + pm_runtime_put_sync(cpsw->dev); > + return ret; > +} > + > static int cpsw_ndo_open(struct net_device *ndev) > { > struct cpsw_priv *priv = netdev_priv(ndev); > @@ -2263,6 +2481,9 @@ static int cpsw_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type, > void *type_data) > { > switch (type) { > + case TC_SETUP_QDISC_CBS: > + return cpsw_set_cbs(ndev, type_data); > + > case TC_SETUP_QDISC_MQPRIO: > return cpsw_set_tc(ndev, type_data); > > -- > 2.17.1 > Reviewed-by: Ilias Apalodimas