Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1040875/?format=api
{ "id": 1040875, "url": "http://patchwork.ozlabs.org/api/patches/1040875/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190212215624.10049-1-jeffrey.t.kirsher@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": "<20190212215624.10049-1-jeffrey.t.kirsher@intel.com>", "list_archive_url": null, "date": "2019-02-12T21:56:24", "name": "[next,S2-v3,04/12] i40e: save PTP time before a device reset", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "46163570e5d5c0a9611c97ab3285b3448302551c", "submitter": { "id": 473, "url": "http://patchwork.ozlabs.org/api/people/473/?format=api", "name": "Kirsher, Jeffrey T", "email": "jeffrey.t.kirsher@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/20190212215624.10049-1-jeffrey.t.kirsher@intel.com/mbox/", "series": [ { "id": 91583, "url": "http://patchwork.ozlabs.org/api/series/91583/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=91583", "date": "2019-02-12T21:56:24", "name": null, "version": 1, "mbox": "http://patchwork.ozlabs.org/series/91583/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1040875/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1040875/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;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.137; helo=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 43zc0D2FcYz9s7h\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 13 Feb 2019 08:55:24 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 4A56B81125;\n\tTue, 12 Feb 2019 21:55:22 +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 c1mao02aZpQv; Tue, 12 Feb 2019 21:55:15 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 1C8F080ADB;\n\tTue, 12 Feb 2019 21:55:15 +0000 (UTC)", "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\n\tby ash.osuosl.org (Postfix) with ESMTP id 924121BF39A\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 12 Feb 2019 21:55:13 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id 8E34980ADB\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 12 Feb 2019 21:55:13 +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 RFdKc2BFndZV for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 12 Feb 2019 21:55:09 +0000 (UTC)", "from mga12.intel.com (mga12.intel.com [192.55.52.136])\n\tby fraxinus.osuosl.org (Postfix) with ESMTPS id 7C20A80ACA\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 12 Feb 2019 21:55:09 +0000 (UTC)", "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t12 Feb 2019 13:55:08 -0800", "from jtkirshe-desk1.jf.intel.com ([134.134.177.96])\n\tby orsmga003.jf.intel.com with ESMTP; 12 Feb 2019 13:55:08 -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.58,362,1544515200\"; d=\"scan'208\";a=\"125958474\"", "From": "Jeff Kirsher <jeffrey.t.kirsher@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Tue, 12 Feb 2019 13:56:24 -0800", "Message-Id": "<20190212215624.10049-1-jeffrey.t.kirsher@intel.com>", "X-Mailer": "git-send-email 2.20.1", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [next S2-v3 04/12] i40e: save PTP time before a\n\tdevice reset", "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": "From: Jacob Keller <jacob.e.keller@intel.com>\n\nIn the case where PTP is running on the hardware clock, but the kernel\nsystem time is not being synced, a device reset can mess up the clock\ntime.\n\nThis occurs because we reset the clock time based on the kernel time\nevery reset. This causes us to potentially completely reset the PTP\ntime, and can cause unexpected behavior in programs like ptp4l.\n\nAvoid this by saving the PTP time prior to device reset, and then\nrestoring using that time after the reset.\n\nDirectly restoring the PTP time we saved isn't perfect, because time\nshould have continued running, but the clock will essentially be stopped\nduring the reset. This is still better than the current solution of\nassuming that the PTP HW clock is synced to the CLOCK_REALTIME.\n\nWe can do even better, by saving the ktime and calculating\na differential, using ktime_get(). This is based on CLOCK_MONOTONIC, and\nallows us to get a fairly precise measure of the time difference between\nsaving and restoring the time.\n\nUsing this, we can update the saved PTP time, and use that as the value\nto write to the hardware clock registers. This, of course is not perfect.\nHowever, it does help ensure that the PTP time is restored as close as\nfeasible to the time it should have been if the reset had not occurred.\n\nDuring device initialization, continue using the system time as the\nsource for the creation of the PTP clock, since this is the best known\ncurrent time source at driver load.\n\nSigned-off-by: Jacob Keller <jacob.e.keller@intel.com>\n---\nv3: added fix to check to see if the PTP flag is enabled\n\n drivers/net/ethernet/intel/i40e/i40e.h | 4 ++\n drivers/net/ethernet/intel/i40e/i40e_main.c | 5 ++\n drivers/net/ethernet/intel/i40e/i40e_ptp.c | 58 +++++++++++++++++++--\n 3 files changed, 63 insertions(+), 4 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h\nindex 3bf9c50c3394..b11255c6be64 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e.h\n+++ b/drivers/net/ethernet/intel/i40e/i40e.h\n@@ -632,6 +632,8 @@ struct i40e_pf {\n \tstruct sk_buff *ptp_tx_skb;\n \tunsigned long ptp_tx_start;\n \tstruct hwtstamp_config tstamp_config;\n+\tstruct timespec64 ptp_prev_hw_time;\n+\tktime_t ptp_reset_start;\n \tstruct mutex tmreg_lock; /* Used to protect the SYSTIME registers. */\n \tu32 ptp_adj_mult;\n \tu32 tx_hwtstamp_timeouts;\n@@ -1132,6 +1134,8 @@ void i40e_ptp_rx_hwtstamp(struct i40e_pf *pf, struct sk_buff *skb, u8 index);\n void i40e_ptp_set_increment(struct i40e_pf *pf);\n int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr);\n int i40e_ptp_get_ts_config(struct i40e_pf *pf, struct ifreq *ifr);\n+void i40e_ptp_save_hw_time(struct i40e_pf *pf);\n+void i40e_ptp_restore_hw_time(struct i40e_pf *pf);\n void i40e_ptp_init(struct i40e_pf *pf);\n void i40e_ptp_stop(struct i40e_pf *pf);\n int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi);\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c\nindex 3b6768980d8c..37f875f759d0 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_main.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c\n@@ -9745,6 +9745,11 @@ static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired)\n \t\t\tdev_warn(&pf->pdev->dev,\n \t\t\t\t \"shutdown_lan_hmc failed: %d\\n\", ret);\n \t}\n+\n+\t/* Save the current PTP time so that we can restore the time after the\n+\t * reset completes.\n+\t */\n+\ti40e_ptp_save_hw_time(pf);\n }\n \n /**\ndiff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c\nindex 5fb4353c742b..66147c3f5f2c 100644\n--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c\n+++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c\n@@ -724,9 +724,56 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf)\n \tpf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;\n \tpf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;\n \n+\t/* Set the previous \"reset\" time to the current Kernel clock time */\n+\tpf->ptp_prev_hw_time = ktime_to_timespec64(ktime_get_real());\n+\tpf->ptp_reset_start = ktime_get();\n+\n \treturn 0;\n }\n \n+/**\n+ * i40e_ptp_save_hw_time - Save the current PTP time as ptp_prev_hw_time\n+ * @pf: Board private structure\n+ *\n+ * Read the current PTP time and save it into pf->ptp_prev_hw_time. This should\n+ * be called at the end of preparing to reset, just before hardware reset\n+ * occurs, in order to preserve the PTP time as close as possible across\n+ * resets.\n+ */\n+void i40e_ptp_save_hw_time(struct i40e_pf *pf)\n+{\n+\t/* don't try to access the PTP clock if it's not enabled */\n+\tif (!(pf->flags & I40E_FLAG_PTP))\n+\t\treturn;\n+\n+\ti40e_ptp_gettimex(&pf->ptp_caps, &pf->ptp_prev_hw_time, NULL);\n+\t/* Get a monotonic starting time for this reset */\n+\tpf->ptp_reset_start = ktime_get();\n+}\n+\n+/**\n+ * i40e_ptp_restore_hw_time - Restore the ptp_prev_hw_time + delta to PTP regs\n+ * @pf: Board private structure\n+ *\n+ * Restore the PTP hardware clock registers. We previously cached the PTP\n+ * hardware time as pf->ptp_prev_hw_time. To be as accurate as possible,\n+ * update this value based on the time delta since the time was saved, using\n+ * CLOCK_MONOTONIC (via ktime_get()) to calculate the time difference.\n+ *\n+ * This ensures that the hardware clock is restored to nearly what it should\n+ * have been if a reset had not occurred.\n+ */\n+void i40e_ptp_restore_hw_time(struct i40e_pf *pf)\n+{\n+\tktime_t delta = ktime_sub(ktime_get(), pf->ptp_reset_start);\n+\n+\t/* Update the previous HW time with the ktime delta */\n+\ttimespec64_add_ns(&pf->ptp_prev_hw_time, ktime_to_ns(delta));\n+\n+\t/* Restore the hardware clock registers */\n+\ti40e_ptp_settime(&pf->ptp_caps, &pf->ptp_prev_hw_time);\n+}\n+\n /**\n * i40e_ptp_init - Initialize the 1588 support after device probe or reset\n * @pf: Board private structure\n@@ -734,6 +781,11 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf)\n * This function sets device up for 1588 support. The first time it is run, it\n * will create a PHC clock device. It does not create a clock device if one\n * already exists. It also reconfigures the device after a reset.\n+ *\n+ * The first time a clock is created, i40e_ptp_create_clock will set\n+ * pf->ptp_prev_hw_time to the current system time. During resets, it is\n+ * expected that this timespec will be set to the last known PTP clock time,\n+ * in order to preserve the clock time as close as possible across a reset.\n **/\n void i40e_ptp_init(struct i40e_pf *pf)\n {\n@@ -765,7 +817,6 @@ void i40e_ptp_init(struct i40e_pf *pf)\n \t\tdev_err(&pf->pdev->dev, \"%s: ptp_clock_register failed\\n\",\n \t\t\t__func__);\n \t} else if (pf->ptp_clock) {\n-\t\tstruct timespec64 ts;\n \t\tu32 regval;\n \n \t\tif (pf->hw.debug_mask & I40E_DEBUG_LAN)\n@@ -786,9 +837,8 @@ void i40e_ptp_init(struct i40e_pf *pf)\n \t\t/* reset timestamping mode */\n \t\ti40e_ptp_set_timestamp_mode(pf, &pf->tstamp_config);\n \n-\t\t/* Set the clock value. */\n-\t\tts = ktime_to_timespec64(ktime_get_real());\n-\t\ti40e_ptp_settime(&pf->ptp_caps, &ts);\n+\t\t/* Restore the clock time based on last known value */\n+\t\ti40e_ptp_restore_hw_time(pf);\n \t}\n }\n \n", "prefixes": [ "next", "S2-v3", "04/12" ] }