Received: by 2002:a25:7ec1:0:0:0:0:0 with SMTP id z184csp711485ybc; Tue, 12 Nov 2019 08:05:29 -0800 (PST) X-Google-Smtp-Source: APXvYqxVZDa4drYu5EZBgZVxd5fSngApGJuTD+DJR0Z0HEarlKH7Cjm8XMHRGsZb/kJcQWSl21M4 X-Received: by 2002:a5d:4585:: with SMTP id p5mr27216548wrq.134.1573574729251; Tue, 12 Nov 2019 08:05:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573574729; cv=none; d=google.com; s=arc-20160816; b=Gx6OMaw91fQuiPpw7JRmRiXGTGzYzUmHxg5n6hOJ0AzUn91dHb+LfwtTSU+l8nCQ9T SjofMR/QxlCwY2zLJUZo+ggzuunj/35eEysW6cJTxsIyPjYNIl4aEDbGKQfAMH214OGZ sLnRouAEgKgSWzW+BM/9Rn3oFfGtNkkp/knj7Euk6HZsQ2Kom+aigX+tp5LPV53DvMDe 7EIPy42iRMwGguqs8qbXEIWV2qnl2p8isDIqOQ8phADkp1GOB7Ga34y2BVBei6Ah0pXY 7KIieSkkCWlxhwDAPy9wTmI/omgti/DcZh+uC/FQR8bWBJtwKDLd4K0bhSadR2kBMQp3 +qyw== 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-disposition:mime-version:references:mail-followup-to :message-id:subject:cc:to:from:date:dkim-signature; bh=J4jwRZqjd4l540cGkxytaRFha/R6Ih/k2goKtfn0EIo=; b=vViR3wQ/dmgsr3t31LlZZ2XCrBBgrhqW56KLR2ZvPmZHywCK3W27aN9GywM8v4hc5S TX1QwkC754YOdMRbx2DMp6bAAVCLPu1u1Iz3kMI6Xl6ExTwBhZk+u34JI/ZMOAx+dA5/ 4QgMH4r+0ZFNYN2av36WprB0qZtMQU+8ymJY6i0iGeYLvzldhxS7JLLHcnrpL1Dmbcku rD4cLXXlpxR21N/Jz7QUNcF9yF2wAXiSGIruetHOLo1vxV4nFmn+WtUGJPUjXiRsS+vI eCFNhAKFR43P5BjSiMpXHyrb9cW26uMRJiMNGOZeSchJ517y+/IQeSBpthuGMDEMhT2H YdsA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=AqOtEItX; 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 r1si12619750edm.57.2019.11.12.08.05.03; Tue, 12 Nov 2019 08:05:29 -0800 (PST) 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=AqOtEItX; 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 S1727140AbfKLQDG (ORCPT + 99 others); Tue, 12 Nov 2019 11:03:06 -0500 Received: from mail-lf1-f67.google.com ([209.85.167.67]:45516 "EHLO mail-lf1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727083AbfKLQDG (ORCPT ); Tue, 12 Nov 2019 11:03:06 -0500 Received: by mail-lf1-f67.google.com with SMTP id v8so13242963lfa.12 for ; Tue, 12 Nov 2019 08:03:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to:user-agent; bh=J4jwRZqjd4l540cGkxytaRFha/R6Ih/k2goKtfn0EIo=; b=AqOtEItXImqKxZHhAJWBsVyFp5jrHd8WvnpVRfxmlFX/7g0KlzyiYdqqWFVd6MS9kM oZFGPUxkIf7I3phqGqetaxRvB80lpfsuzksy3MvI6OgK+ERS/7zBH3jJlfMiHygRrNy0 HwT69WnwiZ3bPP0BY3yDqC7tGpi+8xyDzIN05/AdVfo2/UThFy/WqsrsyQ25XVv7c9Z7 QeRdnejSlEUcQj2GJPkape+TMrbTg5IuVnTxvZ/HB4X+h1PzWgyfscKftKco9A3yywet XOAXo+9204vtPeq4UKHIlVci4JFtdxccW19C2v4uye4oIQXc/3IXWUr+rbI7cmRwqE6n BmfQ== 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 :mail-followup-to:references:mime-version:content-disposition :in-reply-to:user-agent; bh=J4jwRZqjd4l540cGkxytaRFha/R6Ih/k2goKtfn0EIo=; b=K2E5wz3GFDyBHlhnd/lZgF57U6n4XL0rTd/Nz3VgDyFr065pKtudSOe8OHFNd6w+m9 quv5YJbbI/enD++RZ5Ip67yPNkP0wBpaDamkCrWAk0kNxCTdoJ+pZXDageUJNuS5KST0 ZmjrCAYmgp3kLSkprdtIRYybt6olhVAj2Y7HVjcFj53zES8my26gAKBDpcbLMDgh0A0B //mtJ907W//kt7ywCeCLEebXptlzugVzeTpemO9A8kw2/tdanY7WH/86pdcKn81BnurM WiEjYrhY4vxH+EjNNHy6xGhyHklsQMaSGs4ErDYPjh3tOb2AXJs0DfRU9Ogdqhz/9XWr CVLg== X-Gm-Message-State: APjAAAUMQ/VIZLwfzn8hxYCOGUqPEDfO5yWJy/skQKe3PV3xaY7pcYUo jS/IOS83+65GcFuP4JQsiZ8seQ== X-Received: by 2002:ac2:5967:: with SMTP id h7mr19346554lfp.119.1573574583220; Tue, 12 Nov 2019 08:03:03 -0800 (PST) Received: from khorivan (57-201-94-178.pool.ukrtel.net. [178.94.201.57]) by smtp.gmail.com with ESMTPSA id y189sm15028284lfc.9.2019.11.12.08.03.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2019 08:03:02 -0800 (PST) Date: Tue, 12 Nov 2019 18:03:00 +0200 From: Ivan Khoronzhuk To: Po Liu Cc: Claudiu Manoil , "davem@davemloft.net" , "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "vinicius.gomes@intel.com" , Vladimir Oltean , Alexandru Marginean , Xiaoliang Yang , Roy Zang , Mingkai Hu , Jerry Huang , Leo Li Subject: Re: [net-next, 1/2] enetc: Configure the Time-Aware Scheduler via tc-taprio offload Message-ID: <20191112160258.GA1833@khorivan> Mail-Followup-To: Po Liu , Claudiu Manoil , "davem@davemloft.net" , "linux-kernel@vger.kernel.org" , "netdev@vger.kernel.org" , "vinicius.gomes@intel.com" , Vladimir Oltean , Alexandru Marginean , Xiaoliang Yang , Roy Zang , Mingkai Hu , Jerry Huang , Leo Li References: <20191111042715.13444-1-Po.Liu@nxp.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: <20191111042715.13444-1-Po.Liu@nxp.com> User-Agent: Mutt/1.10.1 (2018-07-13) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, Nov 11, 2019 at 04:41:26AM +0000, Po Liu wrote: >ENETC supports in hardware for time-based egress shaping according >to IEEE 802.1Qbv. This patch implement the Qbv enablement by the >hardware offload method qdisc tc-taprio method. >Also update cbdr writeback to up level since control bd ring may >writeback data to control bd ring. > >Signed-off-by: Po Liu >Singed-off-by: Vladimir Oltean >Signed-off-by: Claudiu Manoil >--- > drivers/net/ethernet/freescale/enetc/Makefile | 1 + > drivers/net/ethernet/freescale/enetc/enetc.c | 19 ++- > drivers/net/ethernet/freescale/enetc/enetc.h | 2 + > .../net/ethernet/freescale/enetc/enetc_cbdr.c | 5 +- > .../net/ethernet/freescale/enetc/enetc_hw.h | 150 ++++++++++++++++-- > .../net/ethernet/freescale/enetc/enetc_qos.c | 130 +++++++++++++++ > 6 files changed, 285 insertions(+), 22 deletions(-) > create mode 100644 drivers/net/ethernet/freescale/enetc/enetc_qos.c > >diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile >index d200c27c3bf6..389f722efc43 100644 >--- a/drivers/net/ethernet/freescale/enetc/Makefile >+++ b/drivers/net/ethernet/freescale/enetc/Makefile >@@ -5,6 +5,7 @@ common-objs := enetc.o enetc_cbdr.o enetc_ethtool.o > obj-$(CONFIG_FSL_ENETC) += fsl-enetc.o > fsl-enetc-y := enetc_pf.o enetc_mdio.o $(common-objs) > fsl-enetc-$(CONFIG_PCI_IOV) += enetc_msg.o >+fsl-enetc-$(CONFIG_NET_SCH_TAPRIO) += enetc_qos.o > > obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o > fsl-enetc-vf-y := enetc_vf.o $(common-objs) >diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c >index 3e8f9819f08c..d58dbc2c4270 100644 >--- a/drivers/net/ethernet/freescale/enetc/enetc.c >+++ b/drivers/net/ethernet/freescale/enetc/enetc.c >@@ -1427,8 +1427,7 @@ int enetc_close(struct net_device *ndev) > return 0; > } > >-int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, >- void *type_data) >+int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) > { > struct enetc_ndev_priv *priv = netdev_priv(ndev); > struct tc_mqprio_qopt *mqprio = type_data; >@@ -1436,9 +1435,6 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, > u8 num_tc; > int i; > >- if (type != TC_SETUP_QDISC_MQPRIO) >- return -EOPNOTSUPP; >- > mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; > num_tc = mqprio->num_tc; > >@@ -1483,6 +1479,19 @@ int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, > return 0; > } > >+int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, >+ void *type_data) >+{ >+ switch (type) { >+ case TC_SETUP_QDISC_MQPRIO: >+ return enetc_setup_tc_mqprio(ndev, type_data); This patch is for taprio offload, I see that mqprio is related and is part of taprio offload configuration. But taprio offload has own mqprio settings. The taprio mqprio part is not offloaded with TC_SETUP_QDISC_MQPRIO. So, a combination of mqprio and tario qdiscs used. Could you please share the commands were used for your setup? And couple interesting questions about all of this: - The taprio qdisc has to have mqprio settings, but if it's done with mqprio then it just skipped (by reading tc class num). - If no separate mqprio qdisc configuration then mqprio conf from taprio is set, who should restore tc mappings when taprio qdisc is unloaded? Maybe there is reason to implement TC_SETUP_QDISC_MQPRIO offload in taprio since it's required feature? Would be better to move changes for mqprio in separate patch with explanation. >+ case TC_SETUP_QDISC_TAPRIO: >+ return enetc_setup_tc_taprio(ndev, type_data); >+ default: >+ return -EOPNOTSUPP; >+ } >+} >+ > struct net_device_stats *enetc_get_stats(struct net_device *ndev) > { > struct enetc_ndev_priv *priv = netdev_priv(ndev); >diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h >index 541b4e2073fe..8676631041d5 100644 >--- a/drivers/net/ethernet/freescale/enetc/enetc.h >+++ b/drivers/net/ethernet/freescale/enetc/enetc.h >@@ -244,3 +244,5 @@ int enetc_set_fs_entry(struct enetc_si *si, struct enetc_cmd_rfse *rfse, > void enetc_set_rss_key(struct enetc_hw *hw, const u8 *bytes); > int enetc_get_rss_table(struct enetc_si *si, u32 *table, int count); > int enetc_set_rss_table(struct enetc_si *si, const u32 *table, int count); >+int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd); >+int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data); >diff --git a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c >index de466b71bf8f..201cbc362e33 100644 >--- a/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c >+++ b/drivers/net/ethernet/freescale/enetc/enetc_cbdr.c >@@ -32,7 +32,7 @@ static int enetc_cbd_unused(struct enetc_cbdr *r) > r->bd_count; > } > >-static int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd) >+int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd) > { > struct enetc_cbdr *ring = &si->cbd_ring; > int timeout = ENETC_CBDR_TIMEOUT; >@@ -66,6 +66,9 @@ static int enetc_send_cmd(struct enetc_si *si, struct enetc_cbd *cbd) > if (!timeout) > return -EBUSY; > >+ /* CBD may writeback data, feedback up level */ >+ *cbd = *dest_cbd; >+ > enetc_clean_cbdr(si); > > return 0; >diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h >index 88276299f447..75a7c0f1f8ce 100644 >--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h >+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h >@@ -18,6 +18,7 @@ > #define ENETC_SICTR0 0x18 > #define ENETC_SICTR1 0x1c > #define ENETC_SIPCAPR0 0x20 >+#define ENETC_SIPCAPR0_QBV BIT(4) > #define ENETC_SIPCAPR0_RSS BIT(8) > #define ENETC_SIPCAPR1 0x24 > #define ENETC_SITGTGR 0x30 >@@ -148,6 +149,12 @@ enum enetc_bdr_type {TX, RX}; > #define ENETC_PORT_BASE 0x10000 > #define ENETC_PMR 0x0000 > #define ENETC_PMR_EN GENMASK(18, 16) >+#define ENETC_PMR_PSPEED_MASK GENMASK(11, 8) >+#define ENETC_PMR_PSPEED_10M 0x000 >+#define ENETC_PMR_PSPEED_100M 0x100 >+#define ENETC_PMR_PSPEED_1000M 0x200 >+#define ENETC_PMR_PSPEED_2500M 0x400 >+ > #define ENETC_PSR 0x0004 /* RO */ > #define ENETC_PSIPMR 0x0018 > #define ENETC_PSIPMR_SET_UP(n) BIT(n) /* n = SI index */ >@@ -440,22 +447,6 @@ union enetc_rx_bd { > #define EMETC_MAC_ADDR_FILT_RES 3 /* # of reserved entries at the beginning */ > #define ENETC_MAX_NUM_VFS 2 > >-struct enetc_cbd { >- union { >- struct { >- __le32 addr[2]; >- __le32 opt[4]; >- }; >- __le32 data[6]; >- }; >- __le16 index; >- __le16 length; >- u8 cmd; >- u8 cls; >- u8 _res; >- u8 status_flags; >-}; >- > #define ENETC_CBD_FLAGS_SF BIT(7) /* short format */ > #define ENETC_CBD_STATUS_MASK 0xf > >@@ -554,3 +545,130 @@ static inline void enetc_set_bdr_prio(struct enetc_hw *hw, int bdr_idx, > val |= ENETC_TBMR_SET_PRIO(prio); > enetc_txbdr_wr(hw, bdr_idx, ENETC_TBMR, val); > } >+ >+enum bdcr_cmd_class { >+ BDCR_CMD_UNSPEC = 0, >+ BDCR_CMD_MAC_FILTER, >+ BDCR_CMD_VLAN_FILTER, >+ BDCR_CMD_RSS, >+ BDCR_CMD_RFS, >+ BDCR_CMD_PORT_GCL, >+ BDCR_CMD_RECV_CLASSIFIER, >+ __BDCR_CMD_MAX_LEN, >+ BDCR_CMD_MAX_LEN = __BDCR_CMD_MAX_LEN - 1, >+}; >+ >+/* class 5, command 0 */ >+struct tgs_gcl_conf { >+ u8 atc; /* init gate value */ >+ u8 res[7]; >+ union { >+ struct { >+ u8 res1[4]; >+ __le16 acl_len; >+ u8 res2[2]; >+ }; >+ struct { >+ u32 cctl; >+ u32 ccth; >+ }; >+ }; >+}; >+ >+#define ENETC_CBDR_SGL_IOMEN BIT(0) >+#define ENETC_CBDR_SGL_IPVEN BIT(3) >+#define ENETC_CBDR_SGL_GTST BIT(4) >+#define ENETC_CBDR_SGL_IPV_MASK 0xe >+ >+/* gate control list entry */ >+struct gce { >+ u32 period; >+ u8 gate; >+ u8 res[3]; >+}; >+ >+/* tgs_gcl_conf address point to this data space */ >+struct tgs_gcl_data { >+ u32 btl; >+ u32 bth; >+ u32 ct; >+ u32 cte; >+}; >+ >+/* class 5, command 1 */ >+struct tgs_gcl_query { >+ u8 res[12]; >+ union { >+ struct { >+ __le16 acl_len; /* admin list length */ >+ __le16 ocl_len; /* operation list length */ >+ }; >+ struct { >+ u16 admin_list_len; >+ u16 oper_list_len; >+ }; >+ }; >+}; >+ >+/* tgs_gcl_query command response data format */ >+struct tgs_gcl_resp { >+ u32 abtl; /* base time */ >+ u32 abth; >+ u32 act; /* cycle time */ >+ u32 acte; /* cycle time extend */ >+ u32 cctl; /* config change time */ >+ u32 ccth; >+ u32 obtl; /* operation base time */ >+ u32 obth; >+ u32 oct; /* operation cycle time */ >+ u32 octe; /* operation cycle time extend */ >+ u32 ccel; /* config change error */ >+ u32 cceh; >+}; >+ >+struct enetc_cbd { >+ union{ >+ struct { >+ __le32 addr[2]; >+ union { >+ __le32 opt[4]; >+ struct tgs_gcl_conf gcl_conf; >+ struct tgs_gcl_query gcl_query; >+ }; >+ }; /* Long format */ >+ __le32 data[6]; >+ }; >+ __le16 index; >+ __le16 length; >+ u8 cmd; >+ u8 cls; >+ u8 _res; >+ u8 status_flags; >+}; >+ >+#define ENETC_PTCFPR(n) (0x1910 + (n) * 4) /* n = [0 ..7] */ >+#define ENETC_FPE BIT(31) >+ >+/* Port capability register 0 */ >+#define ENETC_PCAPR0_PSFPM BIT(10) >+#define ENETC_PCAPR0_PSFP BIT(9) >+#define ENETC_PCAPR0_TSN BIT(4) >+#define ENETC_PCAPR0_QBU BIT(3) >+ >+/* port time gating control register */ >+#define ENETC_QBV_PTGCR_OFFSET 0x11a00 >+#define ENETC_QBV_TGE 0x80000000 >+#define ENETC_QBV_TGPE BIT(30) >+#define ENETC_QBV_TGDROP_DISABLE BIT(29) >+ >+/* Port time gating capability register */ >+#define ENETC_QBV_PTGCAPR_OFFSET 0x11a08 >+#define ENETC_QBV_MAX_GCL_LEN_MASK 0xffff >+ >+/* Port time gating admin gate list status register */ >+#define ENETC_QBV_PTGAGLSR_OFFSET 0x11a10 >+#define ENETC_QBV_CFG_PEND_MASK 0x00000002 >+ >+#define ENETC_TGLSTR 0xa200 >+#define ENETC_TGS_MIN_DIS_MASK 0x80000000 >+#define ENETC_MIN_LOOKAHEAD_MASK 0xffff >diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c >new file mode 100644 >index 000000000000..036bb39c7a0b >--- /dev/null >+++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c >@@ -0,0 +1,130 @@ >+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) >+/* Copyright 2019 NXP */ >+ >+#include "enetc.h" >+ >+#include >+ >+static u16 enetc_get_max_gcl_len(struct enetc_hw *hw) >+{ >+ return enetc_rd(hw, ENETC_QBV_PTGCAPR_OFFSET) >+ & ENETC_QBV_MAX_GCL_LEN_MASK; >+} >+ >+static int enetc_setup_taprio(struct net_device *ndev, >+ struct tc_taprio_qopt_offload *admin_conf) >+{ >+ struct enetc_ndev_priv *priv = netdev_priv(ndev); >+ struct enetc_cbd cbd = {.cmd = 0}; >+ struct tgs_gcl_conf *gcl_config; >+ struct tgs_gcl_data *gcl_data; >+ struct gce *gce; >+ dma_addr_t dma; >+ u16 data_size; >+ u16 gcl_len; >+ u32 temp; >+ int i; >+ >+ gcl_len = admin_conf->num_entries; >+ if (gcl_len > enetc_get_max_gcl_len(&priv->si->hw)) >+ return -EINVAL; >+ >+ if (admin_conf->enable) { >+ enetc_wr(&priv->si->hw, >+ ENETC_QBV_PTGCR_OFFSET, >+ temp & (~ENETC_QBV_TGE)); >+ usleep_range(10, 20); >+ enetc_wr(&priv->si->hw, >+ ENETC_QBV_PTGCR_OFFSET, >+ temp | ENETC_QBV_TGE); >+ } else { >+ enetc_wr(&priv->si->hw, >+ ENETC_QBV_PTGCR_OFFSET, >+ temp & (~ENETC_QBV_TGE)); >+ return 0; >+ } >+ >+ /* Configure the (administrative) gate control list using the >+ * control BD descriptor. >+ */ >+ gcl_config = &cbd.gcl_conf; >+ >+ data_size = sizeof(struct tgs_gcl_data) + gcl_len * sizeof(struct gce); >+ >+ gcl_data = kzalloc(data_size, __GFP_DMA | GFP_KERNEL); >+ if (!gcl_data) >+ return -ENOMEM; >+ >+ gce = (struct gce *)(gcl_data + 1); >+ >+ /* Since no initial state config in taprio, set gates open as default. >+ */ >+ gcl_config->atc = 0xff; >+ gcl_config->acl_len = cpu_to_le16(gcl_len); >+ >+ if (!admin_conf->base_time) { >+ gcl_data->btl = >+ cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR0)); >+ gcl_data->bth = >+ cpu_to_le32(enetc_rd(&priv->si->hw, ENETC_SICTR1)); >+ } else { >+ gcl_data->btl = >+ cpu_to_le32(lower_32_bits(admin_conf->base_time)); >+ gcl_data->bth = >+ cpu_to_le32(upper_32_bits(admin_conf->base_time)); >+ } >+ >+ gcl_data->ct = cpu_to_le32(admin_conf->cycle_time); >+ gcl_data->cte = cpu_to_le32(admin_conf->cycle_time_extension); >+ >+ for (i = 0; i < gcl_len; i++) { >+ struct tc_taprio_sched_entry *temp_entry; >+ struct gce *temp_gce = gce + i; >+ >+ temp_entry = &admin_conf->entries[i]; >+ >+ temp_gce->gate = cpu_to_le32(temp_entry->gate_mask); >+ temp_gce->period = cpu_to_le32(temp_entry->interval); >+ } >+ >+ cbd.length = cpu_to_le16(data_size); >+ cbd.status_flags = 0; >+ >+ dma = dma_map_single(&priv->si->pdev->dev, gcl_data, >+ data_size, DMA_TO_DEVICE); >+ if (dma_mapping_error(&priv->si->pdev->dev, dma)) { >+ netdev_err(priv->si->ndev, "DMA mapping failed!\n"); >+ kfree(gcl_data); >+ return -ENOMEM; >+ } >+ >+ cbd.addr[0] = lower_32_bits(dma); >+ cbd.addr[1] = upper_32_bits(dma); >+ cbd.cls = BDCR_CMD_PORT_GCL; >+ >+ /* Updated by ENETC on completion of the configuration >+ * command. A zero value indicates success. >+ */ >+ cbd.status_flags = 0; >+ >+ enetc_send_cmd(priv->si, &cbd); >+ >+ dma_unmap_single(&priv->si->pdev->dev, dma, data_size, DMA_TO_DEVICE); >+ kfree(gcl_data); >+ >+ return 0; >+} >+ >+int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) >+{ >+ struct tc_taprio_qopt_offload *taprio = type_data; >+ struct enetc_ndev_priv *priv = netdev_priv(ndev); >+ int i; >+ >+ for (i = 0; i < priv->num_tx_rings; i++) >+ enetc_set_bdr_prio(&priv->si->hw, >+ priv->tx_ring[i]->index, >+ taprio->enable ? i : 0); >+ >+ return enetc_setup_taprio(ndev, taprio); >+} >-- >2.17.1 > -- Regards, Ivan Khoronzhuk