Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1199191/?format=api
{ "id": 1199191, "url": "http://patchwork.ozlabs.org/api/patches/1199191/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191122020224.1102649-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": "<20191122020224.1102649-2-vinicius.gomes@intel.com>", "list_archive_url": null, "date": "2019-11-22T02:02:21", "name": "[next-queue,v1,1/4] igc: Add basic skeleton for PTP", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "72745533184cff7b0e1516bc180eac9369257d00", "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/20191122020224.1102649-2-vinicius.gomes@intel.com/mbox/", "series": [ { "id": 144449, "url": "http://patchwork.ozlabs.org/api/series/144449/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=144449", "date": "2019-11-22T02:02:20", "name": "igc: Add basic support for Timestamping/PTP", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/144449/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1199191/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1199191/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.138;\n\thelo=whitealder.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 whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\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 47K07S05plz9sPT\n\tfor <incoming@patchwork.ozlabs.org>;\n\tFri, 22 Nov 2019 13:02:43 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 843FE84016;\n\tFri, 22 Nov 2019 02:02:42 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id rB+gcptHnusz; Fri, 22 Nov 2019 02:02:36 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 41FE187C88;\n\tFri, 22 Nov 2019 02:02:35 +0000 (UTC)", "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\tby ash.osuosl.org (Postfix) with ESMTP id 55A4A1BF33D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 22 Nov 2019 02:02:33 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 528888723E\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 22 Nov 2019 02:02:33 +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 P_6agEa5vM0J for <intel-wired-lan@lists.osuosl.org>;\n\tFri, 22 Nov 2019 02:02:31 +0000 (UTC)", "from mga05.intel.com (mga05.intel.com [192.55.52.43])\n\tby fraxinus.osuosl.org (Postfix) with ESMTPS id 1AC9A87245\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 22 Nov 2019 02:02:31 +0000 (UTC)", "from fmsmga008.fm.intel.com ([10.253.24.58])\n\tby fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t21 Nov 2019 18:02:30 -0800", "from vcostago-desk1.jf.intel.com ([10.54.70.26])\n\tby fmsmga008.fm.intel.com with ESMTP; 21 Nov 2019 18:02:30 -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.69,228,1571727600\"; d=\"scan'208\";a=\"205264934\"", "From": "Vinicius Costa Gomes <vinicius.gomes@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Thu, 21 Nov 2019 18:02:21 -0800", "Message-Id": "<20191122020224.1102649-2-vinicius.gomes@intel.com>", "X-Mailer": "git-send-email 2.24.0", "In-Reply-To": "<20191122020224.1102649-1-vinicius.gomes@intel.com>", "References": "<20191122020224.1102649-1-vinicius.gomes@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [next-queue PATCH v1 1/4] igc: Add basic skeleton\n\tfor PTP", "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": "This allows the creation of the /dev/ptpX device for i225, and reading\nand writing the time.\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 | 26 ++\n drivers/net/ethernet/intel/igc/igc_defines.h | 12 +\n drivers/net/ethernet/intel/igc/igc_main.c | 27 ++\n drivers/net/ethernet/intel/igc/igc_ptp.c | 349 +++++++++++++++++++\n drivers/net/ethernet/intel/igc/igc_regs.h | 24 ++\n 6 files changed, 439 insertions(+), 1 deletion(-)\n create mode 100644 drivers/net/ethernet/intel/igc/igc_ptp.c", "diff": "diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile\nindex 88c6f88baac5..49fb1e1965cd 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\n+igc_ethtool.o igc_ptp.o\ndiff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h\nindex 0868677d43ed..31b0ed0aa090 100644\n--- a/drivers/net/ethernet/intel/igc/igc.h\n+++ b/drivers/net/ethernet/intel/igc/igc.h\n@@ -10,6 +10,9 @@\n #include <linux/vmalloc.h>\n #include <linux/ethtool.h>\n #include <linux/sctp.h>\n+#include <linux/ptp_clock_kernel.h>\n+#include <linux/timecounter.h>\n+#include <linux/net_tstamp.h>\n \n #include \"igc_hw.h\"\n \n@@ -45,11 +48,15 @@ extern char igc_driver_version[];\n #define IGC_REGS_LEN\t\t\t740\n #define IGC_RETA_SIZE\t\t\t128\n \n+/* flags controlling PTP/1588 function */\n+#define IGC_PTP_ENABLED\t\t\tBIT(0)\n+\n /* Interrupt defines */\n #define IGC_START_ITR\t\t\t648 /* ~6000 ints/sec */\n #define IGC_FLAG_HAS_MSI\t\tBIT(0)\n #define IGC_FLAG_QUEUE_PAIRS\t\tBIT(3)\n #define IGC_FLAG_DMAC\t\t\tBIT(4)\n+#define IGC_FLAG_PTP\t\t\tBIT(8)\n #define IGC_FLAG_NEED_LINK_UPDATE\tBIT(9)\n #define IGC_FLAG_MEDIA_RESET\t\tBIT(10)\n #define IGC_FLAG_MAS_ENABLE\t\tBIT(12)\n@@ -430,6 +437,20 @@ struct igc_adapter {\n \n \tunsigned long link_check_timeout;\n \tstruct igc_info ei;\n+\n+\tstruct ptp_clock *ptp_clock;\n+\tstruct ptp_clock_info ptp_caps;\n+\tstruct work_struct ptp_tx_work;\n+\tstruct sk_buff *ptp_tx_skb;\n+\tstruct hwtstamp_config tstamp_config;\n+\tunsigned long ptp_tx_start;\n+\tunsigned long last_rx_ptp_check;\n+\tunsigned long last_rx_timestamp;\n+\tunsigned int ptp_flags;\n+\t/* System time value lock */\n+\tspinlock_t tmreg_lock;\n+\tstruct cyclecounter cc;\n+\tstruct timecounter tc;\n };\n \n /* igc_desc_unused - calculate if we have unused descriptors */\n@@ -513,6 +534,11 @@ int igc_add_filter(struct igc_adapter *adapter,\n int igc_erase_filter(struct igc_adapter *adapter,\n \t\t struct igc_nfc_filter *input);\n \n+void igc_ptp_init(struct igc_adapter *adapter);\n+void igc_ptp_reset(struct igc_adapter *adapter);\n+void igc_ptp_stop(struct igc_adapter *adapter);\n+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 #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 f3788f0b95b4..fa345adad5c9 100644\n--- a/drivers/net/ethernet/intel/igc/igc_defines.h\n+++ b/drivers/net/ethernet/intel/igc/igc_defines.h\n@@ -187,6 +187,7 @@\n #define IGC_ICR_RXDMT0\t\tBIT(4)\t/* Rx desc min. threshold (0) */\n #define IGC_ICR_RXO\t\tBIT(6)\t/* Rx overrun */\n #define IGC_ICR_RXT0\t\tBIT(7)\t/* Rx timer intr (ring 0) */\n+#define IGC_ICR_TS\t\tBIT(19) /* Time Sync Interrupt */\n #define IGC_ICR_DRSTA\t\tBIT(30)\t/* Device Reset Asserted */\n \n /* If this bit asserted, the driver should claim the interrupt */\n@@ -209,6 +210,7 @@\n #define IGC_IMS_DRSTA\t\tIGC_ICR_DRSTA\t/* Device Reset Asserted */\n #define IGC_IMS_RXT0\t\tIGC_ICR_RXT0\t/* Rx timer intr */\n #define IGC_IMS_RXDMT0\t\tIGC_ICR_RXDMT0\t/* Rx desc min. threshold */\n+#define IGC_IMS_TS\t\tIGC_ICR_TS\t/* Time Sync Interrupt */\n \n #define IGC_QVECTOR_MASK\t0x7FFC\t\t/* Q-vector mask */\n #define IGC_ITR_VAL_MASK\t0x04\t\t/* ITR value mask */\n@@ -324,6 +326,16 @@\n #define I225_RXPBSIZE_DEFAULT\t0x000000A2 /* RXPBSIZE default */\n #define I225_TXPBSIZE_DEFAULT\t0x04000014 /* TXPBSIZE default */\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+#define IGC_TSICR_TT0\t\tBIT(3) /* Target Time 0 Trigger. */\n+#define IGC_TSICR_TT1\t\tBIT(4) /* Target Time 1 Trigger. */\n+#define IGC_TSICR_AUTT0\t\tBIT(5) /* Auxiliary Timestamp 0 Taken. */\n+#define IGC_TSICR_AUTT1\t\tBIT(6) /* Auxiliary Timestamp 1 Taken. */\n+\n+#define IGC_TSICR_INTERRUPTS\tIGC_TSICR_TXTS\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 9700527dd797..abdb827e646d 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -110,6 +110,9 @@ void igc_reset(struct igc_adapter *adapter)\n \tif (!netif_running(adapter->netdev))\n \t\tigc_power_down_link(adapter);\n \n+\t/* Re-enable PTP, where applicable. */\n+\tigc_ptp_reset(adapter);\n+\n \tigc_get_phy_info(hw);\n }\n \n@@ -4199,6 +4202,24 @@ static int igc_close(struct net_device *netdev)\n \treturn 0;\n }\n \n+/**\n+ * igc_ioctl - Access the hwtstamp interface\n+ * @netdev: network interface device structure\n+ * @ifreq: interface request data\n+ * @cmd: ioctl command\n+ **/\n+static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)\n+{\n+\tswitch (cmd) {\n+\tcase SIOCGHWTSTAMP:\n+\t\treturn igc_ptp_get_ts_config(netdev, ifr);\n+\tcase SIOCSHWTSTAMP:\n+\t\treturn igc_ptp_set_ts_config(netdev, ifr);\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@@ -4210,6 +4231,7 @@ static const struct net_device_ops igc_netdev_ops = {\n \t.ndo_fix_features\t= igc_fix_features,\n \t.ndo_set_features\t= igc_set_features,\n \t.ndo_features_check\t= igc_features_check,\n+\t.ndo_do_ioctl = igc_ioctl,\n };\n \n /* PCIe configuration access */\n@@ -4512,6 +4534,9 @@ static int igc_probe(struct pci_dev *pdev,\n \t /* carrier off reporting is important to ethtool even BEFORE open */\n \tnetif_carrier_off(netdev);\n \n+\t/* do hw tstamp init after resetting */\n+\tigc_ptp_init(adapter);\n+\n \t/* Check if Media Autosense is enabled */\n \tadapter->ei = *ei;\n \n@@ -4554,6 +4579,8 @@ static void igc_remove(struct pci_dev *pdev)\n \tstruct net_device *netdev = pci_get_drvdata(pdev);\n \tstruct igc_adapter *adapter = netdev_priv(netdev);\n \n+\tigc_ptp_stop(adapter);\n+\n \tset_bit(__IGC_DOWN, &adapter->state);\n \n \tdel_timer_sync(&adapter->watchdog_timer);\ndiff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c\nnew file mode 100644\nindex 000000000000..aaf10617d222\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c\n@@ -0,0 +1,349 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (c) 2019 Intel Corporation */\n+\n+#include \"igc.h\"\n+\n+#include <linux/module.h>\n+#include <linux/device.h>\n+#include <linux/pci.h>\n+#include <linux/ptp_classify.h>\n+#include <linux/clocksource.h>\n+\n+#define INCVALUE_MASK\t\t0x7fffffff\n+#define ISGN\t\t\t0x80000000\n+\n+#define IGC_SYSTIM_OVERFLOW_PERIOD\t(HZ * 60 * 9)\n+#define IGC_PTP_TX_TIMEOUT\t\t(HZ * 15)\n+\n+/* SYSTIM read access for I225 */\n+static void igc_ptp_read_i225(struct igc_adapter *adapter,\n+\t\t\t struct timespec64 *ts)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tu32 sec, nsec;\n+\n+\t/* The timestamp latches on lowest register read. For I210/I211, the\n+\t * lowest register is SYSTIMR. Since we only need to provide nanosecond\n+\t * resolution, we can ignore it.\n+\t */\n+\trd32(IGC_SYSTIMR);\n+\tnsec = rd32(IGC_SYSTIML);\n+\tsec = rd32(IGC_SYSTIMH);\n+\n+\tts->tv_sec = sec;\n+\tts->tv_nsec = nsec;\n+}\n+\n+static void igc_ptp_write_i225(struct igc_adapter *adapter,\n+\t\t\t const struct timespec64 *ts)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\n+\t/* Writing the SYSTIMR register is not necessary as it only\n+\t * provides sub-nanosecond resolution.\n+\t */\n+\twr32(IGC_SYSTIML, ts->tv_nsec);\n+\twr32(IGC_SYSTIMH, ts->tv_sec);\n+}\n+\n+static int igc_ptp_adjfine_i225(struct ptp_clock_info *ptp, long scaled_ppm)\n+{\n+\tstruct igc_adapter *igc = container_of(ptp, struct igc_adapter,\n+\t\t\t\t\t ptp_caps);\n+\tstruct igc_hw *hw = &igc->hw;\n+\tint neg_adj = 0;\n+\tu64 rate;\n+\tu32 inca;\n+\n+\tif (scaled_ppm < 0) {\n+\t\tneg_adj = 1;\n+\t\tscaled_ppm = -scaled_ppm;\n+\t}\n+\trate = scaled_ppm;\n+\trate <<= 14;\n+\trate = div_u64(rate, 78125);\n+\n+\tinca = rate & INCVALUE_MASK;\n+\tif (neg_adj)\n+\t\tinca |= ISGN;\n+\n+\twr32(IGC_TIMINCA, inca);\n+\n+\treturn 0;\n+}\n+\n+static int igc_ptp_adjtime_i225(struct ptp_clock_info *ptp, s64 delta)\n+{\n+\tstruct igc_adapter *igc = container_of(ptp, struct igc_adapter,\n+\t\t\t\t\t ptp_caps);\n+\tunsigned long flags;\n+\tstruct timespec64 now, then = ns_to_timespec64(delta);\n+\n+\tspin_lock_irqsave(&igc->tmreg_lock, flags);\n+\n+\tigc_ptp_read_i225(igc, &now);\n+\tnow = timespec64_add(now, then);\n+\tigc_ptp_write_i225(igc, (const struct timespec64 *)&now);\n+\n+\tspin_unlock_irqrestore(&igc->tmreg_lock, flags);\n+\n+\treturn 0;\n+}\n+\n+static int igc_ptp_gettimex64_i225(struct ptp_clock_info *ptp,\n+\t\t\t\t struct timespec64 *ts,\n+\t\t\t\t struct ptp_system_timestamp *sts)\n+{\n+\tstruct igc_adapter *igc = container_of(ptp, struct igc_adapter,\n+\t\t\t\t\t ptp_caps);\n+\tstruct igc_hw *hw = &igc->hw;\n+\tunsigned long flags;\n+\n+\tspin_lock_irqsave(&igc->tmreg_lock, flags);\n+\n+\tptp_read_system_prets(sts);\n+\trd32(IGC_SYSTIMR);\n+\tptp_read_system_postts(sts);\n+\tts->tv_nsec = rd32(IGC_SYSTIML);\n+\tts->tv_sec = rd32(IGC_SYSTIMH);\n+\n+\tspin_unlock_irqrestore(&igc->tmreg_lock, flags);\n+\n+\treturn 0;\n+}\n+\n+static int igc_ptp_settime_i225(struct ptp_clock_info *ptp,\n+\t\t\t\tconst struct timespec64 *ts)\n+{\n+\tstruct igc_adapter *igc = container_of(ptp, struct igc_adapter,\n+\t\t\t\t\t ptp_caps);\n+\tunsigned long flags;\n+\n+\tspin_lock_irqsave(&igc->tmreg_lock, flags);\n+\n+\tigc_ptp_write_i225(igc, ts);\n+\n+\tspin_unlock_irqrestore(&igc->tmreg_lock, flags);\n+\n+\treturn 0;\n+}\n+\n+static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,\n+\t\t\t\t struct ptp_clock_request *rq, int on)\n+{\n+\treturn -EOPNOTSUPP;\n+}\n+\n+static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,\n+\t\t\t\t struct hwtstamp_config *config)\n+{\n+\treturn 0;\n+}\n+\n+void igc_ptp_tx_hang(struct igc_adapter *adapter)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tbool timeout = time_is_before_jiffies(adapter->ptp_tx_start +\n+\t\t\t\t\t IGC_PTP_TX_TIMEOUT);\n+\n+\tif (!adapter->ptp_tx_skb)\n+\t\treturn;\n+\n+\tif (!test_bit(__IGC_PTP_TX_IN_PROGRESS, &adapter->state))\n+\t\treturn;\n+\n+\t/* If we haven't received a timestamp within the timeout, it is\n+\t * reasonable to assume that it will never occur, so we can unlock the\n+\t * timestamp bit when this occurs.\n+\t */\n+\tif (timeout) {\n+\t\tcancel_work_sync(&adapter->ptp_tx_work);\n+\t\tdev_kfree_skb_any(adapter->ptp_tx_skb);\n+\t\tadapter->ptp_tx_skb = NULL;\n+\t\tclear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);\n+\t\tadapter->tx_hwtstamp_timeouts++;\n+\t\t/* Clear the tx valid bit in TSYNCTXCTL register to enable\n+\t\t * interrupt\n+\t\t */\n+\t\trd32(IGC_TXSTMPH);\n+\t\tdev_warn(&adapter->pdev->dev, \"clearing Tx timestamp hang\\n\");\n+\t}\n+}\n+\n+void igc_ptp_tx_work(struct work_struct *work)\n+{\n+}\n+\n+/**\n+ * igc_ptp_set_ts_config - set hardware time stamping config\n+ * @netdev:\n+ * @ifreq:\n+ *\n+ **/\n+int igc_ptp_set_ts_config(struct net_device *netdev, struct ifreq *ifr)\n+{\n+\tstruct igc_adapter *adapter = netdev_priv(netdev);\n+\tstruct hwtstamp_config config;\n+\tint err;\n+\n+\tif (copy_from_user(&config, ifr->ifr_data, sizeof(config)))\n+\t\treturn -EFAULT;\n+\n+\terr = igc_ptp_set_timestamp_mode(adapter, &config);\n+\tif (err)\n+\t\treturn err;\n+\n+\t/* save these settings for future reference */\n+\tmemcpy(&adapter->tstamp_config, &config,\n+\t sizeof(adapter->tstamp_config));\n+\n+\treturn copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?\n+\t\t-EFAULT : 0;\n+}\n+\n+/**\n+ * igc_ptp_get_ts_config - get hardware time stamping config\n+ * @netdev:\n+ * @ifreq:\n+ *\n+ * Get the hwtstamp_config settings to return to the user. Rather than attempt\n+ * to deconstruct the settings from the registers, just return a shadow copy\n+ * of the last known settings.\n+ **/\n+int igc_ptp_get_ts_config(struct net_device *netdev, struct ifreq *ifr)\n+{\n+\tstruct igc_adapter *adapter = netdev_priv(netdev);\n+\tstruct hwtstamp_config *config = &adapter->tstamp_config;\n+\n+\treturn copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?\n+\t\t-EFAULT : 0;\n+}\n+\n+/**\n+ * igc_ptp_init - Initialize PTP functionality\n+ * @adapter: Board private structure\n+ *\n+ * This function is called at device probe to initialize the PTP\n+ * functionality.\n+ */\n+void igc_ptp_init(struct igc_adapter *adapter)\n+{\n+\tstruct net_device *netdev = adapter->netdev;\n+\tstruct igc_hw *hw = &adapter->hw;\n+\n+\tswitch (hw->mac.type) {\n+\tcase igc_i225:\n+\t\tsnprintf(adapter->ptp_caps.name, 16, \"%pm\", netdev->dev_addr);\n+\t\tadapter->ptp_caps.owner = THIS_MODULE;\n+\t\tadapter->ptp_caps.max_adj = 62499999;\n+\t\tadapter->ptp_caps.adjfine = igc_ptp_adjfine_i225;\n+\t\tadapter->ptp_caps.adjtime = igc_ptp_adjtime_i225;\n+\t\tadapter->ptp_caps.gettimex64 = igc_ptp_gettimex64_i225;\n+\t\tadapter->ptp_caps.settime64 = igc_ptp_settime_i225;\n+\t\tadapter->ptp_caps.enable = igc_ptp_feature_enable_i225;\n+\t\tbreak;\n+\tdefault:\n+\t\tadapter->ptp_clock = NULL;\n+\t\treturn;\n+\t}\n+\n+\tspin_lock_init(&adapter->tmreg_lock);\n+\tINIT_WORK(&adapter->ptp_tx_work, igc_ptp_tx_work);\n+\n+\tadapter->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;\n+\tadapter->tstamp_config.tx_type = HWTSTAMP_TX_OFF;\n+\n+\tigc_ptp_reset(adapter);\n+\n+\tadapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,\n+\t\t\t\t\t\t&adapter->pdev->dev);\n+\tif (IS_ERR(adapter->ptp_clock)) {\n+\t\tadapter->ptp_clock = NULL;\n+\t\tdev_err(&adapter->pdev->dev, \"ptp_clock_register failed\\n\");\n+\t} else if (adapter->ptp_clock) {\n+\t\tdev_info(&adapter->pdev->dev, \"added PHC on %s\\n\",\n+\t\t\t adapter->netdev->name);\n+\t\tadapter->ptp_flags |= IGC_PTP_ENABLED;\n+\t}\n+}\n+\n+/**\n+ * igc_ptp_suspend - Disable PTP work items and prepare for suspend\n+ * @adapter: Board private structure\n+ *\n+ * This function stops the overflow check work and PTP Tx timestamp work, and\n+ * will prepare the device for OS suspend.\n+ */\n+void igc_ptp_suspend(struct igc_adapter *adapter)\n+{\n+\tif (!(adapter->ptp_flags & IGC_PTP_ENABLED))\n+\t\treturn;\n+\n+\tcancel_work_sync(&adapter->ptp_tx_work);\n+\tif (adapter->ptp_tx_skb) {\n+\t\tdev_kfree_skb_any(adapter->ptp_tx_skb);\n+\t\tadapter->ptp_tx_skb = NULL;\n+\t\tclear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);\n+\t}\n+}\n+\n+/**\n+ * igc_ptp_stop - Disable PTP device and stop the overflow check.\n+ * @adapter: Board private structure.\n+ *\n+ * This function stops the PTP support and cancels the delayed work.\n+ **/\n+void igc_ptp_stop(struct igc_adapter *adapter)\n+{\n+\tigc_ptp_suspend(adapter);\n+\n+\tif (adapter->ptp_clock) {\n+\t\tptp_clock_unregister(adapter->ptp_clock);\n+\t\tdev_info(&adapter->pdev->dev, \"removed PHC on %s\\n\",\n+\t\t\t adapter->netdev->name);\n+\t\tadapter->ptp_flags &= ~IGC_PTP_ENABLED;\n+\t}\n+}\n+\n+/**\n+ * igc_ptp_reset - Re-enable the adapter for PTP following a reset.\n+ * @adapter: Board private structure.\n+ *\n+ * This function handles the reset work required to re-enable the PTP device.\n+ **/\n+void igc_ptp_reset(struct igc_adapter *adapter)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tunsigned long flags;\n+\n+\t/* reset the tstamp_config */\n+\tigc_ptp_set_timestamp_mode(adapter, &adapter->tstamp_config);\n+\n+\tspin_lock_irqsave(&adapter->tmreg_lock, flags);\n+\n+\tswitch (adapter->hw.mac.type) {\n+\tcase igc_i225:\n+\t\twr32(IGC_TSAUXC, 0x0);\n+\t\twr32(IGC_TSSDP, 0x0);\n+\t\twr32(IGC_TSIM, IGC_TSICR_INTERRUPTS);\n+\t\twr32(IGC_IMS, IGC_IMS_TS);\n+\t\tbreak;\n+\tdefault:\n+\t\t/* No work to do. */\n+\t\tgoto out;\n+\t}\n+\n+\t/* Re-initialize the timer. */\n+\tif (hw->mac.type == igc_i225) {\n+\t\tstruct timespec64 ts64 = ktime_to_timespec64(ktime_get_real());\n+\n+\t\tigc_ptp_write_i225(adapter, &ts64);\n+\t} else {\n+\t\ttimecounter_init(&adapter->tc, &adapter->cc,\n+\t\t\t\t ktime_to_ns(ktime_get_real()));\n+\t}\n+out:\n+\tspin_unlock_irqrestore(&adapter->tmreg_lock, flags);\n+\n+\twrfl();\n+}\ndiff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h\nindex b496c9da8cac..0d2e99884887 100644\n--- a/drivers/net/ethernet/intel/igc/igc_regs.h\n+++ b/drivers/net/ethernet/intel/igc/igc_regs.h\n@@ -211,6 +211,30 @@\n \n #define IGC_I225_PHPM\t0x00E14 /* Phy Power Management */\n \n+/* Time sync registers */\n+#define IGC_TSICR\t0x0B66C /* Time Sync Interrupt Cause */\n+#define IGC_TSIM\t0x0B674 /* Time Sync Interrupt Mask Register */\n+#define IGC_TSAUXC\t0x0B640 /* Timesync Auxiliary Control register */\n+#define IGC_TSYNCRXCTL\t0x0B620 /* Rx Time Sync Control register - RW */\n+#define IGC_TSYNCTXCTL\t0x0B614 /* Tx Time Sync Control register - RW */\n+#define IGC_TSYNCRXCFG\t0x05F50 /* Time Sync Rx Configuration - RW */\n+#define IGC_TSSDP\t0x0003C /* Time Sync SDP Configuration Register - RW */\n+\n+#define IGC_IMIR(_i)\t(0x05A80 + ((_i) * 4)) /* Immediate Interrupt */\n+#define IGC_IMIREXT(_i)\t(0x05AA0 + ((_i) * 4)) /* Immediate INTR Ext*/\n+\n+#define IGC_FTQF(_n)\t(0x059E0 + (4 * (_n))) /* 5-tuple Queue Fltr */\n+/* System Time Registers */\n+#define IGC_SYSTIML\t0x0B600 /* System time register Low - RO */\n+#define IGC_SYSTIMH\t0x0B604 /* System time register High - RO */\n+#define IGC_SYSTIMR\t0x0B6F8 /* System time register Residue */\n+#define IGC_TIMINCA\t0x0B608 /* Increment attributes register - RW */\n+\n+#define IGC_RXSTMPL\t0x0B624 /* Rx timestamp Low - RO */\n+#define IGC_RXSTMPH\t0x0B628 /* Rx timestamp High - RO */\n+#define IGC_TXSTMPL\t0x0B618 /* Tx timestamp value Low - RO */\n+#define IGC_TXSTMPH\t0x0B61C /* Tx timestamp value High - RO */\n+\n /* Management registers */\n #define IGC_MANC\t0x05820 /* Management Control - RW */\n \n", "prefixes": [ "next-queue", "v1", "1/4" ] }