Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1235104/?format=api
{ "id": 1235104, "url": "http://patchwork.ozlabs.org/api/patches/1235104/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200207182443.1501016-2-vinicius.gomes@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20200207182443.1501016-2-vinicius.gomes@intel.com>", "list_archive_url": null, "date": "2020-02-07T18:24:42", "name": "[next-queue,v2,1/2] igc: Add support for taprio offloading", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "6efed35ac79a59094eb33c4954f7cc7abf2e9352", "submitter": { "id": 72272, "url": "http://patchwork.ozlabs.org/api/people/72272/?format=api", "name": "Vinicius Costa Gomes", "email": "vinicius.gomes@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200207182443.1501016-2-vinicius.gomes@intel.com/mbox/", "series": [ { "id": 157388, "url": "http://patchwork.ozlabs.org/api/series/157388/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=157388", "date": "2020-02-07T18:24:41", "name": "igc: Add initial TSN qdiscs offloading", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/157388/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1235104/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1235104/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org; spf=pass (sender SPF authorized)\n\tsmtp.mailfrom=osuosl.org (client-ip=140.211.166.133;\n\thelo=hemlock.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 48DkFZ4Pzrz9sPJ\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 8 Feb 2020 05:23:30 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 1691F87F34;\n\tFri, 7 Feb 2020 18:23:29 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 6JfBsjuQqJKB; Fri, 7 Feb 2020 18:23:27 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 9F18E87ECB;\n\tFri, 7 Feb 2020 18:23:27 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 3CA9F1BF38E\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 7 Feb 2020 18:23:26 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 3447787ECB\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 7 Feb 2020 18:23:26 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id vYC6XEDcs-36 for <intel-wired-lan@lists.osuosl.org>;\n\tFri, 7 Feb 2020 18:23:23 +0000 (UTC)", "from mga11.intel.com (mga11.intel.com [192.55.52.93])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id B474887EC4\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 7 Feb 2020 18:23:23 +0000 (UTC)", "from orsmga005.jf.intel.com ([10.7.209.41])\n\tby fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t07 Feb 2020 10:23:23 -0800", "from vcostago-desk1.jf.intel.com ([10.54.70.26])\n\tby orsmga005.jf.intel.com with ESMTP; 07 Feb 2020 10:23:22 -0800" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.70,414,1574150400\"; d=\"scan'208\";a=\"404899414\"", "From": "Vinicius Costa Gomes <vinicius.gomes@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Fri, 7 Feb 2020 10:24:42 -0800", "Message-Id": "<20200207182443.1501016-2-vinicius.gomes@intel.com>", "X-Mailer": "git-send-email 2.25.0", "In-Reply-To": "<20200207182443.1501016-1-vinicius.gomes@intel.com>", "References": "<20200207182443.1501016-1-vinicius.gomes@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [next-queue PATCH v2 1/2] igc: Add support for\n\ttaprio offloading", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "Adds support for translating taprio schedules into i225 cycles. This\nwill allow schedules to run in the hardware, making the schedules\nenforcement more precise and saving CPU time.\n\nRight now, the only simple schedules are allowed, complex schedules are\nrejected. \"simple\" in this context are schedules that each HW queue is\nopened and closed only once in each cycle.\n\nChanging schedules is still not supported as well.\n\nSigned-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>\n---\n drivers/net/ethernet/intel/igc/Makefile | 2 +-\n drivers/net/ethernet/intel/igc/igc.h | 7 +\n drivers/net/ethernet/intel/igc/igc_defines.h | 13 ++\n drivers/net/ethernet/intel/igc/igc_main.c | 114 +++++++++++++++\n drivers/net/ethernet/intel/igc/igc_regs.h | 12 ++\n drivers/net/ethernet/intel/igc/igc_tsn.c | 139 +++++++++++++++++++\n drivers/net/ethernet/intel/igc/igc_tsn.h | 9 ++\n 7 files changed, 295 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/ethernet/intel/igc/igc_tsn.c\n create mode 100644 drivers/net/ethernet/intel/igc/igc_tsn.h", "diff": "diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile\nindex e3c164c12e10..3652f211f351 100644\n--- a/drivers/net/ethernet/intel/igc/Makefile\n+++ b/drivers/net/ethernet/intel/igc/Makefile\n@@ -8,4 +8,4 @@\n obj-$(CONFIG_IGC) += igc.o\n \n igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \\\n-igc_ethtool.o igc_ptp.o igc_dump.o\n+igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o\ndiff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h\nindex 0014828eec46..4c40dc8f276c 100644\n--- a/drivers/net/ethernet/intel/igc/igc.h\n+++ b/drivers/net/ethernet/intel/igc/igc.h\n@@ -70,6 +70,7 @@ extern char igc_driver_version[];\n #define IGC_FLAG_HAS_MSIX\t\tBIT(13)\n #define IGC_FLAG_VLAN_PROMISC\t\tBIT(15)\n #define IGC_FLAG_RX_LEGACY\t\tBIT(16)\n+#define IGC_FLAG_TSN_QBV_ENABLED\tBIT(17)\n \n #define IGC_FLAG_RSS_FIELD_IPV4_UDP\tBIT(6)\n #define IGC_FLAG_RSS_FIELD_IPV6_UDP\tBIT(7)\n@@ -287,6 +288,9 @@ struct igc_ring {\n \tu8 reg_idx; /* physical index of the ring */\n \tbool launchtime_enable;\t\t/* true if LaunchTime is enabled */\n \n+\tu32 start_time;\n+\tu32 end_time;\n+\n \t/* everything past this point are written often */\n \tu16 next_to_clean;\n \tu16 next_to_use;\n@@ -421,6 +425,9 @@ struct igc_adapter {\n \tu32 max_frame_size;\n \tu32 min_frame_size;\n \n+\tktime_t base_time;\n+\tktime_t cycle_time;\n+\n \t/* OS defined structs */\n \tstruct pci_dev *pdev;\n \t/* lock for statistics */\ndiff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h\nindex 044c0f8d4c16..976fa97b082a 100644\n--- a/drivers/net/ethernet/intel/igc/igc_defines.h\n+++ b/drivers/net/ethernet/intel/igc/igc_defines.h\n@@ -377,6 +377,11 @@\n #define I225_TXPBSIZE_DEFAULT\t0x04000014 /* TXPBSIZE default */\n #define IGC_RXPBS_CFG_TS_EN\t0x80000000 /* Timestamp in Rx buffer */\n \n+#define IGC_TXPBSIZE_TSN\t0x04145145 /* 5k bytes buffer for each queue */\n+\n+#define IGC_DTXMXPKTSZ_TSN\t0x19 /* 1600 bytes of max TX DMA packet size */\n+#define IGC_DTXMXPKTSZ_DEFAULT\t0x98 /* 9728-byte Jumbo frames */\n+\n /* Time Sync Interrupt Causes */\n #define IGC_TSICR_SYS_WRAP\tBIT(0) /* SYSTIM Wrap around. */\n #define IGC_TSICR_TXTS\t\tBIT(1) /* Transmit Timestamp. */\n@@ -431,6 +436,14 @@\n #define IGC_TSYNCTXCTL_START_SYNC\t\t0x80000000 /* initiate sync */\n #define IGC_TSYNCTXCTL_TXSYNSIG\t\t\t0x00000020 /* Sample TX tstamp in PHY sop */\n \n+/* Transmit Scheduling */\n+#define IGC_TQAVCTRL_TRANSMIT_MODE_TSN\t0x00000001\n+#define IGC_TQAVCTRL_ENHANCED_QAV\t0x00000008\n+\n+#define IGC_TXQCTL_STRICT_CYCLE\t\t0x00000002\n+#define IGC_TXQCTL_STRICT_END\t\t0x00000004\n+#define IGC_TXQCTL_PREEMPTIBLE\t\t0x00000008\n+\n /* Receive Checksum Control */\n #define IGC_RXCSUM_CRCOFL\t0x00000800 /* CRC32 offload enable */\n #define IGC_RXCSUM_PCSD\t\t0x00002000 /* packet checksum disabled */\ndiff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c\nindex 3407af11dff8..0cb0c72160ab 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -9,11 +9,13 @@\n #include <linux/udp.h>\n #include <linux/ip.h>\n #include <linux/pm_runtime.h>\n+#include <net/pkt_sched.h>\n \n #include <net/ipv6.h>\n \n #include \"igc.h\"\n #include \"igc_hw.h\"\n+#include \"igc_tsn.h\"\n \n #define DRV_VERSION\t\"0.0.1-k\"\n #define DRV_SUMMARY\t\"Intel(R) 2.5G Ethernet Linux Driver\"\n@@ -106,6 +108,9 @@ void igc_reset(struct igc_adapter *adapter)\n \t/* Re-enable PTP, where applicable. */\n \tigc_ptp_reset(adapter);\n \n+\t/* Re-enable TSN offloading, where applicable. */\n+\tigc_tsn_offload_apply(adapter);\n+\n \tigc_get_phy_info(hw);\n }\n \n@@ -4492,6 +4497,114 @@ static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)\n \t}\n }\n \n+static bool validate_schedule(const struct tc_taprio_qopt_offload *qopt)\n+{\n+\tint queue_uses[IGC_MAX_TX_QUEUES] = { };\n+\tsize_t n;\n+\n+\tif (qopt->cycle_time_extension)\n+\t\treturn false;\n+\n+\tfor (n = 0; n < qopt->num_entries; n++) {\n+\t\tconst struct tc_taprio_sched_entry *e;\n+\t\tint i;\n+\n+\t\te = &qopt->entries[n];\n+\n+\t\t/* i225 only supports \"global\" frame preemption\n+\t\t * settings.\n+\t\t */\n+\t\tif (e->command != TC_TAPRIO_CMD_SET_GATES)\n+\t\t\treturn false;\n+\n+\t\tfor (i = 0; i < IGC_MAX_TX_QUEUES; i++) {\n+\t\t\tif (e->gate_mask & BIT(i))\n+\t\t\t\tqueue_uses[i]++;\n+\n+\t\t\tif (queue_uses[i] > 1)\n+\t\t\t\treturn false;\n+\t\t}\n+\t}\n+\n+\treturn true;\n+}\n+\n+static int igc_save_qbv_schedule(struct igc_adapter *adapter,\n+\t\t\t\t struct tc_taprio_qopt_offload *qopt)\n+{\n+\tu32 start_time = 0, end_time = 0;\n+\tstruct igc_ring *ring;\n+\tsize_t n;\n+\tint i;\n+\n+\tif (!qopt->enable) {\n+\t\tadapter->base_time = 0;\n+\t\treturn 0;\n+\t}\n+\n+\tif (adapter->base_time)\n+\t\treturn -EALREADY;\n+\n+\tif (!validate_schedule(qopt))\n+\t\treturn -EINVAL;\n+\n+\tadapter->cycle_time = qopt->cycle_time;\n+\tadapter->base_time = qopt->base_time;\n+\n+\t/* FIXME: be a little smarter about cases when the gate for a\n+\t * queue stays open for more than one entry.\n+\t */\n+\tfor (n = 0; n < qopt->num_entries; n++) {\n+\t\tstruct tc_taprio_sched_entry *e = &qopt->entries[n];\n+\n+\t\tend_time += e->interval;\n+\n+\t\tfor (i = 0; i < IGC_MAX_TX_QUEUES; i++) {\n+\t\t\tring = adapter->tx_ring[i];\n+\n+\t\t\tif (!(e->gate_mask & BIT(i)))\n+\t\t\t\tcontinue;\n+\n+\t\t\tring->start_time = start_time;\n+\t\t\tring->end_time = end_time;\n+\t\t}\n+\n+\t\tstart_time += e->interval;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int igc_tsn_enable_qbv_scheduling(struct igc_adapter *adapter,\n+\t\t\t\t\t struct tc_taprio_qopt_offload *qopt)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tint err;\n+\n+\tif (hw->mac.type != igc_i225)\n+\t\treturn -EOPNOTSUPP;\n+\n+\terr = igc_save_qbv_schedule(adapter, qopt);\n+\tif (err)\n+\t\treturn err;\n+\n+\treturn igc_tsn_offload_apply(adapter);\n+}\n+\n+static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,\n+\t\t\tvoid *type_data)\n+{\n+\tstruct igc_adapter *adapter = netdev_priv(dev);\n+\n+\tswitch (type) {\n+\tcase TC_SETUP_QDISC_TAPRIO:\n+\t\treturn igc_tsn_enable_qbv_scheduling(adapter, type_data);\n+\n+\tdefault:\n+\t\treturn -EOPNOTSUPP;\n+\t}\n+}\n+\n static const struct net_device_ops igc_netdev_ops = {\n \t.ndo_open\t\t= igc_open,\n \t.ndo_stop\t\t= igc_close,\n@@ -4504,6 +4617,7 @@ static const struct net_device_ops igc_netdev_ops = {\n \t.ndo_set_features\t= igc_set_features,\n \t.ndo_features_check\t= igc_features_check,\n \t.ndo_do_ioctl\t\t= igc_ioctl,\n+\t.ndo_setup_tc = igc_setup_tc,\n };\n \n /* PCIe configuration access */\ndiff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h\nindex d4af53a80f11..96dee3c1a5f7 100644\n--- a/drivers/net/ethernet/intel/igc/igc_regs.h\n+++ b/drivers/net/ethernet/intel/igc/igc_regs.h\n@@ -231,6 +231,18 @@\n \n #define IGC_RXPBS\t0x02404 /* Rx Packet Buffer Size - RW */\n \n+/* Transmit Scheduling Registers */\n+#define IGC_TQAVCTRL 0x3570\n+#define IGC_TXQCTL(_n) (0x3344 + 0x4 * (_n))\n+#define IGC_BASET_L 0x3314\n+#define IGC_BASET_H 0x3318\n+#define IGC_QBVCYCLET 0x331C\n+#define IGC_QBVCYCLET_S 0x3320\n+\n+#define IGC_STQT(_n) (0x3324 + 0x4 * (_n))\n+#define IGC_ENDQT(_n) (0x3334 + 0x4 * (_n))\n+#define IGC_DTXMXPKTSZ 0x355C\n+\n /* System Time Registers */\n #define IGC_SYSTIML\t0x0B600 /* System time register Low - RO */\n #define IGC_SYSTIMH\t0x0B604 /* System time register High - RO */\ndiff --git a/drivers/net/ethernet/intel/igc/igc_tsn.c b/drivers/net/ethernet/intel/igc/igc_tsn.c\nnew file mode 100644\nindex 000000000000..ebd61b89d90e\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c\n@@ -0,0 +1,139 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (c) 2019 Intel Corporation */\n+\n+#include \"igc.h\"\n+\n+/* Returns the TSN specific registers to their default values after\n+ * TSN offloading is disabled.\n+ */\n+static int igc_tsn_disable_offload(struct igc_adapter *adapter)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tu32 tqavctrl;\n+\tint i;\n+\n+\tif (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED))\n+\t\treturn 0;\n+\n+\tadapter->cycle_time = 0;\n+\n+\twr32(IGC_TXPBS, I225_TXPBSIZE_DEFAULT);\n+\twr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_DEFAULT);\n+\n+\ttqavctrl = rd32(IGC_TQAVCTRL);\n+\ttqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |\n+\t\t IGC_TQAVCTRL_ENHANCED_QAV);\n+\twr32(IGC_TQAVCTRL, tqavctrl);\n+\n+\tfor (i = 0; i < adapter->num_tx_queues; i++) {\n+\t\tstruct igc_ring *ring = adapter->tx_ring[i];\n+\n+\t\tring->start_time = 0;\n+\t\tring->end_time = 0;\n+\t\tring->launchtime_enable = false;\n+\n+\t\twr32(IGC_TXQCTL(i), 0);\n+\t\twr32(IGC_STQT(i), 0);\n+\t\twr32(IGC_ENDQT(i), NSEC_PER_SEC);\n+\t}\n+\n+\twr32(IGC_QBVCYCLET_S, NSEC_PER_SEC);\n+\twr32(IGC_QBVCYCLET, NSEC_PER_SEC);\n+\n+\tadapter->flags &= ~IGC_FLAG_TSN_QBV_ENABLED;\n+\n+\treturn 0;\n+}\n+\n+static int igc_tsn_enable_offload(struct igc_adapter *adapter)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tu32 tqavctrl, baset_l, baset_h;\n+\tu32 sec, nsec, cycle;\n+\tktime_t base_time, systim;\n+\tint i;\n+\n+\tif (adapter->flags & IGC_FLAG_TSN_QBV_ENABLED)\n+\t\treturn 0;\n+\n+\tcycle = adapter->cycle_time;\n+\tbase_time = adapter->base_time;\n+\n+\twr32(IGC_TSAUXC, 0);\n+\twr32(IGC_DTXMXPKTSZ, IGC_DTXMXPKTSZ_TSN);\n+\twr32(IGC_TXPBS, IGC_TXPBSIZE_TSN);\n+\n+\ttqavctrl = rd32(IGC_TQAVCTRL);\n+\ttqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;\n+\twr32(IGC_TQAVCTRL, tqavctrl);\n+\n+\twr32(IGC_QBVCYCLET_S, cycle);\n+\twr32(IGC_QBVCYCLET, cycle);\n+\n+\tfor (i = 0; i < adapter->num_tx_queues; i++) {\n+\t\tstruct igc_ring *ring = adapter->tx_ring[i];\n+\t\tu32 txqctl = 0;\n+\n+\t\twr32(IGC_STQT(i), ring->start_time);\n+\t\twr32(IGC_ENDQT(i), ring->end_time);\n+\n+\t\tif (adapter->base_time) {\n+\t\t\t/* If we have a base_time we are in \"taprio\"\n+\t\t\t * mode and we need to be strict about the\n+\t\t\t * cycles: only transmit a packet if it can be\n+\t\t\t * completed during that cycle.\n+\t\t\t */\n+\t\t\ttxqctl |= IGC_TXQCTL_STRICT_CYCLE |\n+\t\t\t\tIGC_TXQCTL_STRICT_END;\n+\t\t}\n+\n+\t\twr32(IGC_TXQCTL(i), txqctl);\n+\t}\n+\n+\tnsec = rd32(IGC_SYSTIML);\n+\tsec = rd32(IGC_SYSTIMH);\n+\n+\tsystim = ktime_set(sec, nsec);\n+\n+\tif (ktime_compare(systim, base_time) > 0) {\n+\t\ts64 n;\n+\n+\t\tn = div64_s64(ktime_sub_ns(systim, base_time), cycle);\n+\t\tbase_time = ktime_add_ns(base_time, (n + 1) * cycle);\n+\t}\n+\n+\tbaset_h = div_s64_rem(base_time, NSEC_PER_SEC, &baset_l);\n+\n+\twr32(IGC_BASET_H, baset_h);\n+\twr32(IGC_BASET_L, baset_l);\n+\n+\tadapter->flags |= IGC_FLAG_TSN_QBV_ENABLED;\n+\n+\treturn 0;\n+}\n+\n+int igc_tsn_offload_apply(struct igc_adapter *adapter)\n+{\n+\tbool is_any_enabled = adapter->base_time;\n+\n+\tif (!(adapter->flags & IGC_FLAG_TSN_QBV_ENABLED) && !is_any_enabled)\n+\t\treturn 0;\n+\n+\tif (!is_any_enabled) {\n+\t\tint err = igc_tsn_disable_offload(adapter);\n+\n+\t\tif (err < 0)\n+\t\t\treturn err;\n+\n+\t\t/* The BASET registers aren't cleared when writing\n+\t\t * into them, force a reset if the interface is\n+\t\t * running.\n+\t\t */\n+\t\tif (netif_running(adapter->netdev))\n+\t\t\tschedule_work(&adapter->reset_task);\n+\n+\t\treturn 0;\n+\t}\n+\n+\treturn igc_tsn_enable_offload(adapter);\n+}\ndiff --git a/drivers/net/ethernet/intel/igc/igc_tsn.h b/drivers/net/ethernet/intel/igc/igc_tsn.h\nnew file mode 100644\nindex 000000000000..8c34be0d9aae\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/igc/igc_tsn.h\n@@ -0,0 +1,9 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (c) 2018 Intel Corporation */\n+\n+#ifndef _IGC_TSN_H_\n+#define _IGC_TSN_H_\n+\n+int igc_tsn_offload_apply(struct igc_adapter *adapter);\n+\n+#endif /* _IGC_BASE_H */\n", "prefixes": [ "next-queue", "v2", "1/2" ] }