Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1231616/?format=api
{ "id": 1231616, "url": "http://patchwork.ozlabs.org/api/patches/1231616/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20200130213455.191163-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": "<20200130213455.191163-2-vinicius.gomes@intel.com>", "list_archive_url": null, "date": "2020-01-30T21:34:54", "name": "[next-queue,v1,1/2] igc: Add support for taprio offloading", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "61181bbfec0be220c82eb0a6fafeb07d5c0cffda", "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/20200130213455.191163-2-vinicius.gomes@intel.com/mbox/", "series": [ { "id": 156101, "url": "http://patchwork.ozlabs.org/api/series/156101/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=156101", "date": "2020-01-30T21:34:53", "name": "igc: Add initial TSN qdiscs offloading", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/156101/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1231616/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1231616/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.137;\n\thelo=fraxinus.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 fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\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 487trm63WVz9sR1\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 31 Jan 2020 08:33:44 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 459778698B;\n\tThu, 30 Jan 2020 21:33:43 +0000 (UTC)", "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id DDTx3Q8nF7Oz; Thu, 30 Jan 2020 21:33:41 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id E9B348693C;\n\tThu, 30 Jan 2020 21:33:41 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 706231BF4D6\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Jan 2020 21:33:40 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 6CCC586B6F\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Jan 2020 21:33:40 +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 32Edtrnjsdfa for <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Jan 2020 21:33:37 +0000 (UTC)", "from mga01.intel.com (mga01.intel.com [192.55.52.88])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id A27C786A2E\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tThu, 30 Jan 2020 21:33:37 +0000 (UTC)", "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t30 Jan 2020 13:33:37 -0800", "from vcostago-desk1.jf.intel.com ([10.54.70.26])\n\tby fmsmga001.fm.intel.com with ESMTP; 30 Jan 2020 13:33:36 -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,382,1574150400\"; d=\"scan'208\";a=\"320201449\"", "From": "Vinicius Costa Gomes <vinicius.gomes@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Thu, 30 Jan 2020 13:34:54 -0800", "Message-Id": "<20200130213455.191163-2-vinicius.gomes@intel.com>", "X-Mailer": "git-send-email 2.25.0", "In-Reply-To": "<20200130213455.191163-1-vinicius.gomes@intel.com>", "References": "<20200130213455.191163-1-vinicius.gomes@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [next-queue PATCH v1 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 | 10 ++\n drivers/net/ethernet/intel/igc/igc_defines.h | 20 +++\n drivers/net/ethernet/intel/igc/igc_main.c | 113 +++++++++++++++\n drivers/net/ethernet/intel/igc/igc_regs.h | 12 ++\n drivers/net/ethernet/intel/igc/igc_tsn.c | 137 +++++++++++++++++++\n 6 files changed, 293 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/ethernet/intel/igc/igc_tsn.c", "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 5e9c2dd8b8e4..34300f551d84 100644\n--- a/drivers/net/ethernet/intel/igc/igc.h\n+++ b/drivers/net/ethernet/intel/igc/igc.h\n@@ -67,6 +67,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@@ -284,6 +285,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@@ -418,6 +422,10 @@ 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+\tbool baset_set;\n+\n \t/* OS defined structs */\n \tstruct pci_dev *pdev;\n \t/* lock for statistics */\n@@ -565,6 +573,8 @@ int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr);\n int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr);\n void igc_ptp_tx_hang(struct igc_adapter *adapter);\n \n+int igc_tsn_offload_apply(struct igc_adapter *adapter);\n+\n #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))\n \n #define IGC_TXD_DCMD\t(IGC_ADVTXD_DCMD_EOP | IGC_ADVTXD_DCMD_RS)\ndiff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h\nindex 3c03962bde5e..d400786fc413 100644\n--- a/drivers/net/ethernet/intel/igc/igc_defines.h\n+++ b/drivers/net/ethernet/intel/igc/igc_defines.h\n@@ -374,6 +374,10 @@\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 /* Each queue will have 5k bytes buffer */\n+\n+#define IGC_DTXMXPKTSZ_TSN\t0x19 /* 1600 bytes of Maximum TX DMA packet size (64B resolution) */\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@@ -428,6 +432,22 @@\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_QUEUE_MODE_LAUNCHT\t0x00000001\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+#define IGC_BASET_L_AUTO_SET\t\t0x40000000\n+#define IGC_BASET_L_COPY_H\t\t0x80000000\n+\n+#define IGC_QBVCYCLET_S_PLUS1\t\t0x80000000\n+\n+#define IGC_TSAUXC_DISABLE_SYSTIME_0\tBIT(31)\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 2b79e22d5e5f..1bb663e826e9 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -9,6 +9,7 @@\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@@ -106,6 +107,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@@ -4491,6 +4495,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\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\t/* i225 only supports \"global\" frame\n+\t\t\t * preemption settings\n+\t\t\t */\n+\t\t\tif (e->command != TC_TAPRIO_CMD_SET_GATES)\n+\t\t\t\treturn false;\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@@ -4503,6 +4615,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..affffce0e870\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/igc/igc_tsn.c\n@@ -0,0 +1,137 @@\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+\n+\ttqavctrl = rd32(IGC_TQAVCTRL);\n+\ttqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN | 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 err;\n+\t}\n+\n+\treturn igc_tsn_enable_offload(adapter);\n+}\n", "prefixes": [ "next-queue", "v1", "1/2" ] }