From patchwork Mon Jan 15 12:44:56 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksey Makarov X-Patchwork-Id: 860885 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=CAVIUMNETWORKS.onmicrosoft.com header.i=@CAVIUMNETWORKS.onmicrosoft.com header.b="iWuISERJ"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zKvWc4hp2z9sCZ for ; Tue, 16 Jan 2018 00:36:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966666AbeAOMpm (ORCPT ); Mon, 15 Jan 2018 07:45:42 -0500 Received: from mail-by2nam03on0082.outbound.protection.outlook.com ([104.47.42.82]:4224 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S966654AbeAOMpd (ORCPT ); Mon, 15 Jan 2018 07:45:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=p33fJww2d4C031GcmXRjPQmRTXWU8QJyOSpsk5FFgkA=; b=iWuISERJMAfPmCxwwrXBJtnqkQmqp8+CVVxTfrQ0i6waYJjIMQTMgATbt92el2MguHMONEPBTkwtIuX3CRIKEYcNEaMgHlu+11aaiFK3yhsSF7wczA6KT3ZCgtCwIpY8k0P1r6M82OkmDgCH/1+X2jrD1OP7uxQXGsMTS+vbEag= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Aleksey.Makarov@cavium.com; Received: from localhost.localdomain (5.45.71.246) by BN3PR07MB2481.namprd07.prod.outlook.com (10.167.4.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.407.7; Mon, 15 Jan 2018 12:45:29 +0000 From: Aleksey Makarov To: netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, "Goutham, Sunil" , Radoslaw Biernacki , Aleksey Makarov , Robert Richter , David Daney , Richard Cochran , Philippe Ombredanne , Joe Perches Subject: [PATCH net-next v6 1/2] net: add support for Cavium PTP coprocessor Date: Mon, 15 Jan 2018 18:44:56 +0600 Message-Id: <20180115124500.14872-2-aleksey.makarov@cavium.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180115124500.14872-1-aleksey.makarov@cavium.com> References: <20180115124500.14872-1-aleksey.makarov@cavium.com> MIME-Version: 1.0 X-Originating-IP: [5.45.71.246] X-ClientProxiedBy: AM5P189CA0003.EURP189.PROD.OUTLOOK.COM (10.161.53.16) To BN3PR07MB2481.namprd07.prod.outlook.com (10.167.4.22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: c7e61b1d-2c5d-4eb4-478d-08d55c15dd82 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(4604075)(4534125)(4602075)(4627221)(201703031133081)(201702281549075)(2017052603307)(7153060)(7193020); SRVR:BN3PR07MB2481; X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 3:DLnQ6UNMcGhiy51BiMOILmH4v51XrDIZH892qfmVvHFH6cs2HsmWk9oaVmapR36E3Jk6+Pe5GcwGDBHfE2F/Nk8znGy0uxtRRzlVa6FlrEnBypYeffIrRhlaJ6ZKKgdvSbQSPTPABlytZSs9WEQ4iUgDzrIJMyScaXhmMEoK3EwqsYfzthFXm9ZjlvPReHnCbqeNlUXF1YtcfB29i2OCg+9uuVn+FO0420JE0F64TbjoPLxLdmWEbGTo0zpLddJw; 25:5qixSuH8iLmvyD1NKLN7UtLRI5uyyX7XYpDp2n52A3MZbUjjPA7e5jrX3WMly0e9iM2JgxbBCsImBmXAyaNkY5iaST2cx6H63gYupt2yEO7lugm9UHrvIMpIs4GmvO1JbuT1jwYXEuICHcj8euhloN7wd2FQ3tawTv2aNSuVlguHNtjgtnLBZ4cyhL3XdyjvlBDIQ1XJ9+z7OWhr42rtsh7um3024LASGcOJ875srTt/tcnXOATP3ePGqYkzKc94GxrSmfZsbrcMOZY6zNqDp04/0eysLIPEEDClK+R6zZKzJ8LrJd4mQzLpTNHnQgSwtzEaYsIXGaH7oXKV6cm3eg==; 31:4zpLCouPXrAmnTZcmMb0dxQ4ROg+8OYYJu2g+tANldi3zJ2AwSExuCU0BnI50/khbXfwYfD+Ot6WfqkeecSpybG47Dnrh12F7WuHvai+Whmc+KIQyqhle6rYcBGTg3TwoTrpMrY5YC7GfT5N+K0RWG/Mh5lQl8i+f/JzMaEGrS9OXWBS9Sm0pw9Ey6v5JN5Sb0nKgmmfsucSVpzpmX6FexLuztg4/jvFbZ/6CXKHDXg= X-MS-TrafficTypeDiagnostic: BN3PR07MB2481: X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 20:XIFQxW6B8WMyoU+bGYQ54eH7P8NUI9cCYF4pNRyq8MiA9AD/YzxluBqtw11sSAa9Lgs2D7LDaWJPeW3A5JEunnl6kGLKzEHRzQv8gUV152SKnIgApInDeB72CdYwswoEzFDRn69u+AORt0LSaILAJIlq1PXtS9IvvGJZdhj8r6buNcObuvG2I7U3cbw1eUMuMUpIrDPs545rbnFhHjtQFJqte8wSiKk8WpW5c0laBfZqqIUA/g6Iqo2/D19u/HS1uzMKo+CQ7lcWhmKL5nHFHDsJ9XtR/28InTILHMcYQHqMecGzYbyLS7XBNtWUTvcGsJ+Ht8Ni6TpnHI1u397EfcuFJrzJmqJLWZ8YuzVT6QIUREpLS/jl5m4VYcII9hU4bVTcuOCwcVosp3lM7rx06i0Fzhu6Z45DwJuS0/MplPoVT9JoaATbf4gp5beqW7xM3Qnk0qLXEpftsT+4vrBTOKLHKBbQcfAMbqMR0WDkx8l4PBQyT+fq5w/RbeZ37pPp; 4:SsC6t8T9DH8W52dVMOyRWk/U0WoFtUKqWAg5ApUWyQQm5kfiOg3VMZmnlGk8YlpWV/ter4/eWmoZc4jVSNwRe0Q2YQvh9vnyErAk7mlnEg0fSXBCrsxl7U8ouKAOnfGzSfEQbz1KrfQwvAQb6OjTeqU40IdOgyo45RiM80pH5Cpe2JRZiEbsaNOzCKNJdvsTz3FzL88CLrd4mbr5usCnxmdNKi0y4J2Zrb9qq5n3iZpBuJL3XAH4YrnuHayhRP4qfDvHCOH72hPUZ2BCwB3SvQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040470)(2401047)(8121501046)(5005006)(3002001)(3231023)(944501161)(10201501046)(93006095)(93001095)(6041268)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(20161123562045)(20161123558120)(6072148)(201708071742011); SRVR:BN3PR07MB2481; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:BN3PR07MB2481; X-Forefront-PRVS: 0553CBB77A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6069001)(366004)(39380400002)(39850400004)(396003)(376002)(346002)(189003)(199004)(3846002)(6116002)(81156014)(81166006)(8936002)(50226002)(1076002)(47776003)(478600001)(66066001)(72206003)(68736007)(8676002)(2906002)(7736002)(305945005)(2361001)(2351001)(37156001)(105586002)(106356001)(71446004)(50466002)(48376002)(36756003)(51416003)(16526018)(6512007)(16586007)(54906003)(5660300001)(575784001)(86362001)(39060400002)(316002)(4326008)(53936002)(6486002)(76176011)(59450400001)(25786009)(97736004)(2950100002)(6666003)(6506007)(6916009)(386003)(52116002); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR07MB2481; H:localhost.localdomain; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 23:geG1thOUa60vLLMEO63WZrEnKjfP62dTNskOsCzQZcaqMHJZP3LBnQWPCM8jpw51RB7y4fjCxzw7AINxACt1PRkjk+rFBBjNoYFY6WQdbix0W9GLzcPSEQZPMj6RtwK2G/9sreSlAkLg2Sd8gK1gstEbBMCyA9y7n+GveaUIhcaFikNPDGVNi8XvVL0olAvEwykbbcO3mydp3rpWOiz9oQA+q5x/NO6uJwyntUIB5ooury/CAeL/gQKPkcOrh/GFhXyUw35gNTJHNil9XIfVQakp2eTo2fNlQnnoeRGQx/MwqjBg6rahgUHVGnJ0BVrx8hFvXCuA8CloEFCrM0HTjQ8Htj06LfjGmdtlgWdRvvE495bYKlsFIRjklu1TogFCkFhBpL8ApytBdcI672qAJ5HiDQdj2WeZREedQBkFWUEB32NsucpRm9C7i3qSYtZXcOo+CwelxZ7Va8iECFDtJA/apLImgPRuEqMG1FDj+xBl7NBVsyndZ3yZlkCgCqT9a53T9Br9g/MYl3qjSmnLXvbDCuFMdTcd/VqUa8+zVe+dFCRlzP3tjg6ruD6oQosW6OA5zxFxdad7WXz98d/+1FPBe8RSA3J7KWRLCQ3eOjbk4f51ZynJmqoSwFzQwJ2FdgPkkW0rn2iwBXviRRWWO51t2yDU/wx9EC8Mb8oia7DDewDTgDnsWZc06ea9LDseJs7+pylDItkJrrYLTQJsTsBAb7UuUqPA8LjjamCngaK0OyTjOsqykcrzAuJC7hp6wuIlGdRP2MnTjWuqJKgshwiuygqU9SsiKT4t876LP1N02D8I+nnCQ0E869R8km2os8+Mtdp4nJ8WFvsJlM8ULy8+QkTTerJA9lAkRE+DFDCQSuFAtEe+mKN42kP9J46O1z+1GCpmGQpcElC+UdFrPa+O2aQpLhE4DimoNjmFeeo7+f764Xu+IUiKIicuvwjBrVcJ2GZhDHAXm0bhLg4vJWOcsY/NiMnkYeV8npunGHg60LOP9y8gjuNsBq+o3L+IxNTC1M3KJ1qLxi9US+PlI5/xum7l742qwWmbVczshm+tpS3iwwE5Alql6mItIqy2VymyfGthloHM6LlOlEm4av4jr5iwlPaJVL513xs5E55BO8gj5gDqIn49nl+Ux4wWnDV5TC9ZddXeeu6zebmkInhxQ+Qu1o8GuBPibmeFiXKUN9bHXWrrmumQfWgFxBSW/puOXOWfAiszlPP8qIg5ozNgwq3r35Z5evjZTpOSPSfBo3tgA6LbkiWD1O60lDlFxIdpIqBTGgVi+5Jjzzvp3zNLsK/uDTnFZsqWRPS7BAs= X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 6:dW6yzVC+EEPoxUgFKwa2uJlmT+fnRrdcd1RDSsM3yRyb9JM7e3hN9jqsLZBdhYrisc6SBkhRY8cMAPGOMEbAKn2ek1n8Plu7SQyzkfTGXRjeelAg5MHtij3h/Pwspxo/kya2hteyirpANTAe9+G04AAt5sPzymgEQ8zFAQM9grvRdKPjCjSgKaPPjGuDFfbs3NPd4m9ygft9Pt/6pSWxCjhYA82GMpiv/SVuRd0qsod2aFnpjd82g4E1B/H1/QGBLRdMKbqo1Q43TBkStOvJQNPCjhQ+KB+vsoB7PuRzoYD8UeRxos6lUluEQ7eOpSg5h7ALcCnchX8VRuZ8LhsSYccVCfC5cUkE6yDT7QpSKMA=; 5:pqMdoBQo35Xw3Y/b8/CHAr9igApR0qweT6h40ZwPbOSZspiqwDfIgKxvRegeTPgPqraibwuGaP/q1B4plWFmjHNzSfrVG3HHHHgl9RNaHo+JKs16crqAm7riKUToJD9vVwgCbNVbTcVCTR/54sD2D8m2APg/58YUFNnCYH9+l34=; 24:jKW1f+pqI0MemzUR9ZWNj0EySF2z1eBmYlIKt8Y2ry80aFGYFNSOOY7RO1QNW4j9H2dCHG/arR3ioQ9juyAOfytf/PbsIyKjRJUlnVeLQPQ=; 7:rKpXo/8BvJEQQSHzTnZp2JCVKFYcXWv9/J4PfSA7kPW/O+DDKu4m2Mi0QntNYliohVNSoshGDz8FXr1VOfGO9KqOwTWo68dBmj8ZLgWFAaVdHG1hMGccsIXM7ritSVpjq2tXZZ533D8pWoBu0SQCUfBCUXxDf7nqBEqTNm+bbRoIQBUHS5/e1eve4HROKLoJtxdf9rlX9pGSjRqmXB8cLGSkiUTgiacvKCQz3sEOSafIXuaG//SIn/IlHICSUPVr SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jan 2018 12:45:29.7071 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: c7e61b1d-2c5d-4eb4-478d-08d55c15dd82 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2481 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Radoslaw Biernacki This patch adds support for the Precision Time Protocol Clocks and Timestamping hardware found on Cavium ThunderX processors. Signed-off-by: Radoslaw Biernacki Signed-off-by: Aleksey Makarov Acked-by: Philippe Ombredanne --- drivers/net/ethernet/cavium/Kconfig | 12 + drivers/net/ethernet/cavium/Makefile | 1 + drivers/net/ethernet/cavium/common/Makefile | 1 + drivers/net/ethernet/cavium/common/cavium_ptp.c | 353 ++++++++++++++++++++++++ drivers/net/ethernet/cavium/common/cavium_ptp.h | 70 +++++ 5 files changed, 437 insertions(+) create mode 100644 drivers/net/ethernet/cavium/common/Makefile create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.c create mode 100644 drivers/net/ethernet/cavium/common/cavium_ptp.h diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 63be75eb34d2..96586c0b4490 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -50,6 +50,18 @@ config THUNDER_NIC_RGX This driver supports configuring XCV block of RGX interface present on CN81XX chip. +config CAVIUM_PTP + tristate "Cavium PTP coprocessor as PTP clock" + depends on 64BIT + imply PTP_1588_CLOCK + default y + ---help--- + This driver adds support for the Precision Time Protocol Clocks and + Timestamping coprocessor (PTP) found on Cavium processors. + PTP provides timestamping mechanism that is suitable for use in IEEE 1588 + Precision Time Protocol or other purposes. Timestamps can be used in + BGX, TNS, GTI, and NIC blocks. + config LIQUIDIO tristate "Cavium LiquidIO support" depends on 64BIT diff --git a/drivers/net/ethernet/cavium/Makefile b/drivers/net/ethernet/cavium/Makefile index 872da9f7c31a..946bba84e81d 100644 --- a/drivers/net/ethernet/cavium/Makefile +++ b/drivers/net/ethernet/cavium/Makefile @@ -1,6 +1,7 @@ # # Makefile for the Cavium ethernet device drivers. # +obj-$(CONFIG_NET_VENDOR_CAVIUM) += common/ obj-$(CONFIG_NET_VENDOR_CAVIUM) += thunder/ obj-$(CONFIG_NET_VENDOR_CAVIUM) += liquidio/ obj-$(CONFIG_NET_VENDOR_CAVIUM) += octeon/ diff --git a/drivers/net/ethernet/cavium/common/Makefile b/drivers/net/ethernet/cavium/common/Makefile new file mode 100644 index 000000000000..dd8561b8060b --- /dev/null +++ b/drivers/net/ethernet/cavium/common/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_CAVIUM_PTP) += cavium_ptp.o diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c new file mode 100644 index 000000000000..c87c9c684a33 --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0 +/* cavium_ptp.c - PTP 1588 clock on Cavium hardware + * Copyright (c) 2003-2015, 2017 Cavium, Inc. + */ + +#include +#include +#include +#include + +#include "cavium_ptp.h" + +#define DRV_NAME "Cavium PTP Driver" + +#define PCI_DEVICE_ID_CAVIUM_PTP 0xA00C +#define PCI_DEVICE_ID_CAVIUM_RST 0xA00E + +#define PCI_PTP_BAR_NO 0 +#define PCI_RST_BAR_NO 0 + +#define PTP_CLOCK_CFG 0xF00ULL +#define PTP_CLOCK_CFG_PTP_EN BIT(0) +#define PTP_CLOCK_LO 0xF08ULL +#define PTP_CLOCK_HI 0xF10ULL +#define PTP_CLOCK_COMP 0xF18ULL + +#define RST_BOOT 0x1600ULL +#define CLOCK_BASE_RATE 50000000ULL + +static u64 ptp_cavium_clock_get(void) +{ + struct pci_dev *pdev; + void __iomem *base; + u64 ret = CLOCK_BASE_RATE * 16; + + pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_RST, NULL); + if (!pdev) + goto error; + + base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO); + if (!base) + goto error_put_pdev; + + ret = CLOCK_BASE_RATE * ((readq(base + RST_BOOT) >> 33) & 0x3f); + + iounmap(base); + +error_put_pdev: + pci_dev_put(pdev); + +error: + return ret; +} + +struct cavium_ptp *cavium_ptp_get(void) +{ + struct cavium_ptp *ptp; + struct pci_dev *pdev; + + pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, + PCI_DEVICE_ID_CAVIUM_PTP, NULL); + if (!pdev) + return ERR_PTR(-ENODEV); + + ptp = pci_get_drvdata(pdev); + if (!ptp) + ptp = ERR_PTR(-EPROBE_DEFER); + if (IS_ERR(ptp)) + pci_dev_put(pdev); + + return ptp; +} +EXPORT_SYMBOL(cavium_ptp_get); + +void cavium_ptp_put(struct cavium_ptp *ptp) +{ + pci_dev_put(ptp->pdev); +} +EXPORT_SYMBOL(cavium_ptp_put); + +/** + * cavium_ptp_adjfine() - Adjust ptp frequency + * @ptp: PTP clock info + * @scaled_ppm: how much to adjust by, in parts per million, but with a + * 16 bit binary fractional field + */ +static int cavium_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + u64 comp; + u64 adj; + bool neg_adj = false; + + if (scaled_ppm < 0) { + neg_adj = true; + scaled_ppm = -scaled_ppm; + } + + /* The hardware adds the clock compensation value to the PTP clock + * on every coprocessor clock cycle. Typical convention is that it + * represent number of nanosecond betwen each cycle. In this + * convention compensation value is in 64 bit fixed-point + * representation where upper 32 bits are number of nanoseconds + * and lower is fractions of nanosecond. + * The scaled_ppm represent the ratio in "parts per bilion" by which the + * compensation value should be corrected. + * To calculate new compenstation value we use 64bit fixed point + * arithmetic on following formula + * comp = tbase + tbase * scaled_ppm / (1M * 2^16) + * where tbase is the basic compensation value calculated initialy + * in cavium_ptp_init() -> tbase = 1/Hz. Then we use endian + * independent structure definition to write data to PTP register. + */ + comp = ((u64)1000000000ull << 32) / clock->clock_rate; + adj = comp * scaled_ppm; + adj >>= 16; + adj = div_u64(adj, 1000000ull); + comp = neg_adj ? comp - adj : comp + adj; + + spin_lock_irqsave(&clock->spin_lock, flags); + writeq(comp, clock->reg_base + PTP_CLOCK_COMP); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + return 0; +} + +/** + * cavium_ptp_adjtime() - Adjust ptp time + * @ptp: PTP clock info + * @delta: how much to adjust by, in nanosecs + */ +static int cavium_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + + spin_lock_irqsave(&clock->spin_lock, flags); + timecounter_adjtime(&clock->time_counter, delta); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + /* Sync, for network driver to get latest value */ + smp_mb(); + + return 0; +} + +/** + * cavium_ptp_gettime() - Get hardware clock time with adjustment + * @ptp: PTP clock info + * @ts: timespec + */ +static int cavium_ptp_gettime(struct ptp_clock_info *ptp_info, + struct timespec64 *ts) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + u64 nsec; + + spin_lock_irqsave(&clock->spin_lock, flags); + nsec = timecounter_read(&clock->time_counter); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + *ts = ns_to_timespec64(nsec); + + return 0; +} + +/** + * cavium_ptp_settime() - Set hardware clock time. Reset adjustment + * @ptp: PTP clock info + * @ts: timespec + */ +static int cavium_ptp_settime(struct ptp_clock_info *ptp_info, + const struct timespec64 *ts) +{ + struct cavium_ptp *clock = + container_of(ptp_info, struct cavium_ptp, ptp_info); + unsigned long flags; + u64 nsec; + + nsec = timespec64_to_ns(ts); + + spin_lock_irqsave(&clock->spin_lock, flags); + timecounter_init(&clock->time_counter, &clock->cycle_counter, nsec); + spin_unlock_irqrestore(&clock->spin_lock, flags); + + return 0; +} + +/** + * cavium_ptp_enable() - Request to enable or disable an ancillary feature. + * @ptp: PTP clock info + * @rq: request + * @on: is it on + */ +static int cavium_ptp_enable(struct ptp_clock_info *ptp_info, + struct ptp_clock_request *rq, int on) +{ + return -EOPNOTSUPP; +} + +static u64 cavium_ptp_cc_read(const struct cyclecounter *cc) +{ + struct cavium_ptp *clock = + container_of(cc, struct cavium_ptp, cycle_counter); + + return readq(clock->reg_base + PTP_CLOCK_HI); +} + +static int cavium_ptp_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct device *dev = &pdev->dev; + struct cavium_ptp *clock; + struct cyclecounter *cc; + u64 clock_cfg; + u64 clock_comp; + int err; + + clock = devm_kzalloc(dev, sizeof(*clock), GFP_KERNEL); + if (!clock) { + err = -ENOMEM; + goto error; + } + + clock->pdev = pdev; + + err = pcim_enable_device(pdev); + if (err) + goto error_free; + + err = pcim_iomap_regions(pdev, 1 << PCI_PTP_BAR_NO, pci_name(pdev)); + if (err) + goto error_free; + + clock->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO]; + + spin_lock_init(&clock->spin_lock); + + cc = &clock->cycle_counter; + cc->read = cavium_ptp_cc_read; + cc->mask = CYCLECOUNTER_MASK(64); + cc->mult = 1; + cc->shift = 0; + + timecounter_init(&clock->time_counter, &clock->cycle_counter, + ktime_to_ns(ktime_get_real())); + + clock->clock_rate = ptp_cavium_clock_get(); + + clock->ptp_info = (struct ptp_clock_info) { + .owner = THIS_MODULE, + .name = "ThunderX PTP", + .max_adj = 1000000000ull, + .n_ext_ts = 0, + .n_pins = 0, + .pps = 0, + .adjfine = cavium_ptp_adjfine, + .adjtime = cavium_ptp_adjtime, + .gettime64 = cavium_ptp_gettime, + .settime64 = cavium_ptp_settime, + .enable = cavium_ptp_enable, + }; + + clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG); + clock_cfg |= PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG); + + clock_comp = ((u64)1000000000ull << 32) / clock->clock_rate; + writeq(clock_comp, clock->reg_base + PTP_CLOCK_COMP); + + clock->ptp_clock = ptp_clock_register(&clock->ptp_info, dev); + if (!clock->ptp_clock) { + err = -ENODEV; + goto error_stop; + } + if (IS_ERR(clock->ptp_clock)) { + err = PTR_ERR(clock->ptp_clock); + goto error_stop; + } + + pci_set_drvdata(pdev, clock); + return 0; + +error_stop: + clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG); + pcim_iounmap_regions(pdev, 1 << PCI_PTP_BAR_NO); + +error_free: + devm_kfree(dev, clock); + +error: + /* For `cavium_ptp_get()` we need to differentiate between the case + * when the core has not tried to probe this device and the case when + * the probe failed. In the later case we pretend that the + * initialization was successful and keep the error in + * `dev->driver_data`. + */ + pci_set_drvdata(pdev, ERR_PTR(err)); + return 0; +} + +static void cavium_ptp_remove(struct pci_dev *pdev) +{ + struct cavium_ptp *clock = pci_get_drvdata(pdev); + u64 clock_cfg; + + if (IS_ERR_OR_NULL(clock)) + return; + + ptp_clock_unregister(clock->ptp_clock); + + clock_cfg = readq(clock->reg_base + PTP_CLOCK_CFG); + clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, clock->reg_base + PTP_CLOCK_CFG); +} + +static const struct pci_device_id cavium_ptp_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVICE_ID_CAVIUM_PTP) }, + { 0, } +}; + +static struct pci_driver cavium_ptp_driver = { + .name = DRV_NAME, + .id_table = cavium_ptp_id_table, + .probe = cavium_ptp_probe, + .remove = cavium_ptp_remove, +}; + +static int __init cavium_ptp_init_module(void) +{ + return pci_register_driver(&cavium_ptp_driver); +} + +static void __exit cavium_ptp_cleanup_module(void) +{ + pci_unregister_driver(&cavium_ptp_driver); +} + +module_init(cavium_ptp_init_module); +module_exit(cavium_ptp_cleanup_module); + +MODULE_DESCRIPTION(DRV_NAME); +MODULE_AUTHOR("Cavium Networks "); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(pci, cavium_ptp_id_table); diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.h b/drivers/net/ethernet/cavium/common/cavium_ptp.h new file mode 100644 index 000000000000..be2bafc7beeb --- /dev/null +++ b/drivers/net/ethernet/cavium/common/cavium_ptp.h @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* cavium_ptp.h - PTP 1588 clock on Cavium hardware + * Copyright (c) 2003-2015, 2017 Cavium, Inc. + */ + +#ifndef CAVIUM_PTP_H +#define CAVIUM_PTP_H + +#include +#include + +struct cavium_ptp { + struct pci_dev *pdev; + + /* Serialize access to cycle_counter, time_counter and hw_registers */ + spinlock_t spin_lock; + struct cyclecounter cycle_counter; + struct timecounter time_counter; + void __iomem *reg_base; + + u32 clock_rate; + + struct ptp_clock_info ptp_info; + struct ptp_clock *ptp_clock; +}; + +#if IS_ENABLED(CONFIG_CAVIUM_PTP) + +struct cavium_ptp *cavium_ptp_get(void); +void cavium_ptp_put(struct cavium_ptp *ptp); + +static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp) +{ + unsigned long flags; + u64 ret; + + spin_lock_irqsave(&ptp->spin_lock, flags); + ret = timecounter_cyc2time(&ptp->time_counter, tstamp); + spin_unlock_irqrestore(&ptp->spin_lock, flags); + + return ret; +} + +static inline int cavium_ptp_clock_index(struct cavium_ptp *clock) +{ + return ptp_clock_index(clock->ptp_clock); +} + +#else + +static inline struct cavium_ptp *cavium_ptp_get(void) +{ + return ERR_PTR(-ENODEV); +} + +static inline void cavium_ptp_put(struct cavium_ptp *ptp) {} + +static inline u64 cavium_ptp_tstamp2time(struct cavium_ptp *ptp, u64 tstamp) +{ + return 0; +} + +static inline int cavium_ptp_clock_index(struct cavium_ptp *clock) +{ + return -1; +} + +#endif + +#endif From patchwork Mon Jan 15 12:44:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksey Makarov X-Patchwork-Id: 860886 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=CAVIUMNETWORKS.onmicrosoft.com header.i=@CAVIUMNETWORKS.onmicrosoft.com header.b="eFIaJcGb"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zKvY64kkwz9sCZ for ; Tue, 16 Jan 2018 00:37:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1030473AbeAONhC (ORCPT ); Mon, 15 Jan 2018 08:37:02 -0500 Received: from mail-by2nam03on0080.outbound.protection.outlook.com ([104.47.42.80]:37568 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S933322AbeAOMpj (ORCPT ); Mon, 15 Jan 2018 07:45:39 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=cc8OlLCdTLpTOB/CAtRmJ/gLgO0pZLH56u4vW8pd5Rk=; b=eFIaJcGbzOZNpX7ymyjYgYktgsyisUDRkCj+IxVBMyQNJZpGIz9ofnEnnXj0zCkyHv8+CVGwTaxbMlEdrmhkznzuENAwX2z0sm+KjUOPwUxbp2kCttoTS5BJZ/ruwwXITROerLyckmgbiT6uRcA+o17t8xWvhyDzdwruEuJ07h4= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Aleksey.Makarov@cavium.com; Received: from localhost.localdomain (5.45.71.246) by BN3PR07MB2481.namprd07.prod.outlook.com (10.167.4.22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.407.7; Mon, 15 Jan 2018 12:45:35 +0000 From: Aleksey Makarov To: netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, "Goutham, Sunil" , Radoslaw Biernacki , Aleksey Makarov , Robert Richter , David Daney , Richard Cochran , Philippe Ombredanne , Joe Perches , Sunil Goutham Subject: [PATCH net-next v6 2/2] net: thunderx: add timestamping support Date: Mon, 15 Jan 2018 18:44:57 +0600 Message-Id: <20180115124500.14872-3-aleksey.makarov@cavium.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180115124500.14872-1-aleksey.makarov@cavium.com> References: <20180115124500.14872-1-aleksey.makarov@cavium.com> MIME-Version: 1.0 X-Originating-IP: [5.45.71.246] X-ClientProxiedBy: AM5P189CA0003.EURP189.PROD.OUTLOOK.COM (10.161.53.16) To BN3PR07MB2481.namprd07.prod.outlook.com (10.167.4.22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: bb495f30-f16f-46c4-cc6e-08d55c15e0d7 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(4604075)(4534125)(4602075)(4627221)(201703031133081)(201702281549075)(2017052603307)(7153060)(7193020); SRVR:BN3PR07MB2481; X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 3:rhC2D/0TfSN/s2smQbQ1P+UFm1X6GorNxXjpQ4K5Z40mtQmZH7s/GC4EqQlI3erz7fm3lQSxsMOXifV7dGOuCpPbZAA+lFn+IRJRB2VvymCXSQXMkcpFUrXXoP4DMpTKd/DHr4natn+4LRBfprgy2kweiW1ev4MKNRv8vV1jOSLYLea6hYSR+kX8WBy+4CdsYnjKUJKzsTFLA/QhfGLdJ+OJzpoQrMBmtY5G3pu+c1Lay4KhE8yhpFYVB/c6fn74; 25:GOdTxWFoIGjj3C+8RD8zzEzxaaO+tofkuMkRQ9TyVem4lYShNJ7GvVFa1hXd+pPTufMWIFRlPgLF476a6JZujRpb5KywJTx6pDQUMlZfMlycsAGsluCy6QBNTAv6Rc5COfTBPIMEocUmdNbmXPDJ7+NR1FrBaq/6znp7CSB2WzfPgEHHf1Wsn+d5mzqtoK3xCF30T/vTlnilR9+h/SP0amLJO0PmmfKT2uSHRQ7Z6iuwXYdeKB2MnjQ4y1/JaWt5K2dhXntYPZ6YcsPa5DUc4xsAc/9ovUGVEUYrIT1MpXTFpF2Jcz/jD7TIGxMNYcgQwxDg74ROyTjX679hlSMZ+Q==; 31:HInXvNGorsxUHtPhSiCmhtWGe7SHvPpX4Dx7t8RXw0lmlvmZnt+c7F6Cxq+GqRwuciTZ2ZXxrdYYTZ5DjxaeR55L3jWP0OEYuLtmUl+vLX0wy7oEdCIVFZ8WB/oejoi9D3XLvLMM18hoR3Dca7UCwpHmZwpttO4Ntt8dNGwaCaP3mlW5Nl9E3X3y+aQdNV9Ol5EFkhD6zO3gQc/2Tv7DWx2tsKWjONIIouzpLzLQ5Sg= X-MS-TrafficTypeDiagnostic: BN3PR07MB2481: X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 20:/+PePi8pnR2lcDmnXy+IY/9mno2cRUWuimja6sgnmukn3Xw9x0N43M1cqhTpBzZqyGrJt5Caw0UlBztm9nx1bqEcg4AdLdevrAx+miSy2UPc11eemLI/Pg72sAGQrWUJAb+yhrkXczmKTg98Upakc+YwOIVijnN9tf80VNBvlyJsF4X02frzaGumswDnA7bSDmT2HeSpc/f1CQrUPJS/sasfKCKGTwEXnhbbRFVcKXkjnCyq86CixLjZCyGFiuvCCiw26nOT5vnSgbFR9b+7cWugJi8jIii7yzTwgbGy0fgt0p2/6qjl9kH6t2Eer5/RYgGkAStfVXaG0rei70OyqHBhVXy9ha+CQDjCH6ObMPRWkLxthmS6BJF++2j10xzB5ghIvqR9yEAjwBB+FyVBAopYqTdApgZlYlkBcFlRZD1f+ZmyzwCyOsBwqC15SpCL0JKk5G9ltXbGWEkJwpstF60XrX1LOOUjwvaIFXamwbGqJWrb/qTvOYL80m6/KowY; 4:O9sQ7Cujwzixz+dzIPcMsmDugtkM25/dX3yzwK4BtdU88ytFuyJYMTp/wjOB0HHb4mOEXhD2ohDCWvCrZ/IPGaUQGpco1RHe5FLBuWh48hbctxWgbbgUllBYlPeNEXGtV9LBrCTfjLg/0IFQrmb4W8lu7rQhnDDFK7stXcmIek1Uk6w9wvSN0yd3ijEmfJsp2MctpmrxUSWH/+U4YGnDg6u3tX4C7RDRoDm03CWyUdrbIrIW+TuXxJ1gPN0WRhKyStPfVVgdqksSE14hPD28TQ== X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040470)(2401047)(8121501046)(5005006)(3002001)(3231023)(944501161)(10201501046)(93006095)(93001095)(6041268)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(20161123562045)(20161123558120)(6072148)(201708071742011); SRVR:BN3PR07MB2481; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:BN3PR07MB2481; X-Forefront-PRVS: 0553CBB77A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6069001)(366004)(39380400002)(39850400004)(396003)(376002)(346002)(189003)(199004)(3846002)(6116002)(81156014)(81166006)(8936002)(50226002)(1076002)(47776003)(478600001)(66066001)(72206003)(68736007)(8676002)(2906002)(7736002)(305945005)(2361001)(2351001)(37156001)(105586002)(106356001)(71446004)(50466002)(48376002)(36756003)(51416003)(16526018)(6512007)(16586007)(54906003)(5660300001)(575784001)(86362001)(39060400002)(316002)(4326008)(53936002)(6486002)(76176011)(107886003)(59450400001)(25786009)(97736004)(2950100002)(6666003)(6506007)(6916009)(386003)(52116002); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR07MB2481; H:localhost.localdomain; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 23:V2JCkFCDU9LUIW/mhsP3qFBR1Ah06FNCEsKN9DEzcusFsE1e43gQi2NI4fuD3KZ6poQNlyUZ2ITVEYf6SOlqw02wiP6EvwM3j6F/8kkdxTm6hFAoXF/SuY+L33qCN4UbC9t+EYuFwU12PhuDI42QeJHG+dsdC7qB91uhuRfSsHyKZJfDPVIdt3dL0pVeMrUDjS1BbAJhdJ6lJU4CxbpmLkh4cTQNKL6JeLccIoGaunxmqkU1J5SeDwY8N0A9IrFg9CkDv0sGXzxQmi4Q4tAzq2axSNuZJtFBttE82QAGaZ20dV/SR9L9FINM8L3OjRcUl8gA0u+V3qi4YdGjflaJ+B+6buiQqjyCSAztoHqiyo+YlDWwc2rj2s9dkoCVR8wtvQpaB1gD2RrjFbzpbRmKu84vLRvbZLHNfpExPZ/iP1dJ+D7ev3/rR+CxSjlt8CWqtJ4fu13uIcGmpjJ8fbYxLsKhXHcDB9tsAmO8PZgcL3fU8WPtM1o+A/CCGeYLacen8ZBxr3V7Caw1F/j8Z9ret8zq/EOrCwj1+aIQ+7v3PJLAGMgCM1Dl+LInYGoK1SKFwv0+lcMTkJR1eHImW+1UMuJKkI/XmGPjEwfhkU8YArHoqzkDEJfys7DxaHRYrcTSQTrln+dw55t0Mveuz/0jkOk3qnGrfa11+LqLZ4EyP0q2VBw6R33TTa1HJLpOY1NwyZtuLTZqW7dVneb+SQR4ByN2qkgpIFVlhQO1mZofD0LH5MGWXZ1+E1n7N9ndWE0phc+28bGYr6LQPFBnF8HwYK7RtVZYefmJHDs0K96+Itp2Hxi3IbkvhYyc6umo49dtZ9YCOYOsb4c2Dd7xHFac9f0mLEcd05v5lLVVqi+sSfeUOhmTSsLFfZtu2X+HogH3arrySg2Y8tv5EWm+nOkthkp+8Mq58HHaV+Qynyh7LLnJ/Pt5wJRwE+HMRWyuiRkOjQC7wgDnGFpPU9t5b3vCy8dVJIFBka+fB8OnjUqGdKMW95JX0IXbPt7fuoWuXs6lpp2nOindAvrLBmQ+62tH6+iCsGaFhY8q8oHL6YG95YK0qPn9th2lIbAIJm07hcFvOHbZIlTIElz4P1sUMor6BnUs95k+O9dQk2mzR3yjCpI9SELQvYfVXsbwn85nKrqYwrKjNzUV5RI5Q+cbSvNHcloIURwCunRY6KcjRqrNZD8mviyIzSieuZ5csSAKPTDUfO6W9j+WzZCzYfR5E0/JwbhIkBadATiHdjUjP+ZzNyBdIEMDIMloaNg4ArGnCN0XgbsdYvj4w4vyk4viZfsDECfIEWJIyS9Xuy6RSbnLh9RullOL93Zfqqd4YAyzAVT2 X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2481; 6:5+1TakSSQCvxa4/lFMHJe3mrVNCFgFk9jhsaAkJC+scUhdqGbXKLjQEePoiqDoHoLDseCU8GJ/HaHr4MTh4StaSMWie1SvdlhV+6nUsmD7/fMPloLD0ePhCji3k7o2UKkgfwlQshAtYugMVVwbGE3uw+Fgoc2aIX9wkcVLq4ZrL7uOs0TCabkfGEQ/osO2J1LNauTfDgBgLuzMWvChJnHvIM6gARsVgSc7nqJesAKP7vToageMkZfb5ZShfdmKwebn5RctNem3qJp61K2hObTjnQnlQlus1MDOxJEqoiKnCJI5xOORh8yyVkE9bEnEm6YwNu7eFlwkRfaYYVJyJ3TTruCL4fVkufLeb5lB9LiyM=; 5:+QEJvZuHbjPkscaxbLsQ5BoFfp8rDFdY4IAr0yDLOuIzBIjqMXLyOTjCcYnsqPOSHgQ/yfKfw/nTxD+IjAM9w2szACL7XXIEXILNgRcfKATJGpCzH7DieOEnYbnWWbW4cB5QyhzNMSce7MEP3+PZM7tyejoaTbpyOcnNbiN2OEE=; 24:splfVUKf2l1z9UMVaOAu0Ys/F45pTjmhhmI92OUWx4Y7vsRKtoLSiF286E1j83q6dp+60CSqXHGuhbuRey/Rweb43ctLoaWW5wuM9GgoS84=; 7:9ncXbHTukEwLBhxNA0qe0GnGI0W9v5ABbpqvIVF9V5t18hwd2heXKz0ZpeuS2AVin5t6s8pAck0+aoTJfN5NsOJIG9BtKlIoltkCcb5k3g0alGZzluiQV974ZrjsOMzruvA0ij4riW+YUHSwBOpaN5ZZIVLbUBQ7r0anLtiqL2ft/LaI7RavuaVeoEvJ8EgQY3m2LHWYrIugoxbyTXWVITvhLFz9Ec0HE5g8sWM09XBEp4ocPZUfjZSY2YjxF/Ad SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jan 2018 12:45:35.0976 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: bb495f30-f16f-46c4-cc6e-08d55c15e0d7 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 711e4ccf-2e9b-4bcf-a551-4094005b6194 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2481 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Sunil Goutham This adds timestamping support for both receive and transmit paths. On the receive side no filters are supported i.e either all pkts will get a timestamp appended infront of the packet or none. On the transmit side HW doesn't support timestamp insertion but only generates a separate CQE with transmitted packet's timestamp. Also HW supports only one packet at a time for timestamping on the transmit side. Signed-off-by: Sunil Goutham Signed-off-by: Aleksey Makarov Acked-by: Philippe Ombredanne --- drivers/net/ethernet/cavium/Kconfig | 1 + drivers/net/ethernet/cavium/thunder/nic.h | 36 +++++ drivers/net/ethernet/cavium/thunder/nic_main.c | 56 ++++++- drivers/net/ethernet/cavium/thunder/nic_reg.h | 1 + .../net/ethernet/cavium/thunder/nicvf_ethtool.c | 29 +++- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 169 ++++++++++++++++++++- drivers/net/ethernet/cavium/thunder/nicvf_queues.c | 26 ++++ drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 29 ++++ drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 4 + 9 files changed, 345 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 96586c0b4490..043e3c11c42b 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -27,6 +27,7 @@ config THUNDER_NIC_PF config THUNDER_NIC_VF tristate "Thunder Virtual function driver" + imply CAVIUM_PTP depends on 64BIT ---help--- This driver supports Thunder's NIC virtual function diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index 4a02e618e318..4cacce5d2b16 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -263,6 +263,8 @@ struct nicvf_drv_stats { struct u64_stats_sync syncp; }; +struct cavium_ptp; + struct nicvf { struct nicvf *pnicvf; struct net_device *netdev; @@ -312,6 +314,33 @@ struct nicvf { struct tasklet_struct qs_err_task; struct work_struct reset_task; + /* PTP timestamp */ + struct cavium_ptp *ptp_clock; + /* Inbound timestamping is on */ + bool hw_rx_tstamp; + /* When the packet that requires timestamping is sent, hardware inserts + * two entries to the completion queue. First is the regular + * CQE_TYPE_SEND entry that signals that the packet was sent. + * The second is CQE_TYPE_SEND_PTP that contains the actual timestamp + * for that packet. + * `ptp_skb` is initialized in the handler for the CQE_TYPE_SEND + * entry and is used and zeroed in the handler for the CQE_TYPE_SEND_PTP + * entry. + * So `ptp_skb` is used to hold the pointer to the packet between + * the calls to CQE_TYPE_SEND and CQE_TYPE_SEND_PTP handlers. + */ + struct sk_buff *ptp_skb; + /* `tx_ptp_skbs` is set when the hardware is sending a packet that + * requires timestamping. Cavium hardware can not process more than one + * such packet at once so this is set each time the driver submits + * a packet that requires timestamping to the send queue and clears + * each time it receives the entry on the completion queue saying + * that such packet was sent. + * So `tx_ptp_skbs` prevents driver from submitting more than one + * packet that requires timestamping to the hardware for transmitting. + */ + atomic_t tx_ptp_skbs; + /* Interrupt coalescing settings */ u32 cq_coalesce_usecs; u32 msg_enable; @@ -371,6 +400,7 @@ struct nicvf { #define NIC_MBOX_MSG_LOOPBACK 0x16 /* Set interface in loopback */ #define NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17 /* Reset statistics counters */ #define NIC_MBOX_MSG_PFC 0x18 /* Pause frame control */ +#define NIC_MBOX_MSG_PTP_CFG 0x19 /* HW packet timestamp */ #define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */ #define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */ @@ -521,6 +551,11 @@ struct pfc { u8 fc_tx; }; +struct set_ptp { + u8 msg; + bool enable; +}; + /* 128 bit shared memory between PF and each VF */ union nic_mbx { struct { u8 msg; } msg; @@ -540,6 +575,7 @@ union nic_mbx { struct set_loopback lbk; struct reset_stat_cfg reset_stat; struct pfc pfc; + struct set_ptp ptp; }; #define NIC_NODE_ID_MASK 0x03 diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 8f1dd55b3e08..8325577d7442 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -426,13 +426,22 @@ static void nic_init_hw(struct nicpf *nic) /* Enable backpressure */ nic_reg_write(nic, NIC_PF_BP_CFG, (1ULL << 6) | 0x03); - /* TNS and TNS bypass modes are present only on 88xx */ + /* TNS and TNS bypass modes are present only on 88xx + * Also offset of this CSR has changed in 81xx and 83xx. + */ if (nic->pdev->subsystem_device == PCI_SUBSYS_DEVID_88XX_NIC_PF) { /* Disable TNS mode on both interfaces */ nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG, - (NIC_TNS_BYPASS_MODE << 7) | BGX0_BLOCK); + (NIC_TNS_BYPASS_MODE << 7) | + BGX0_BLOCK | (1ULL << 16)); nic_reg_write(nic, NIC_PF_INTF_0_1_SEND_CFG | (1 << 8), - (NIC_TNS_BYPASS_MODE << 7) | BGX1_BLOCK); + (NIC_TNS_BYPASS_MODE << 7) | + BGX1_BLOCK | (1ULL << 16)); + } else { + /* Configure timestamp generation timeout to 10us */ + for (i = 0; i < nic->hw->bgx_cnt; i++) + nic_reg_write(nic, NIC_PF_INTFX_SEND_CFG | (i << 3), + (1ULL << 16)); } nic_reg_write(nic, NIC_PF_INTF_0_1_BP_CFG, @@ -880,6 +889,44 @@ static void nic_pause_frame(struct nicpf *nic, int vf, struct pfc *cfg) } } +/* Enable or disable HW timestamping by BGX for pkts received on a LMAC */ +static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp) +{ + struct pkind_cfg *pkind; + u8 lmac, bgx_idx; + u64 pkind_val, pkind_idx; + + if (vf >= nic->num_vf_en) + return; + + bgx_idx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + + pkind_idx = lmac + bgx_idx * MAX_LMAC_PER_BGX; + pkind_val = nic_reg_read(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3)); + pkind = (struct pkind_cfg *)&pkind_val; + + if (ptp->enable && !pkind->hdr_sl) { + /* Skiplen to exclude 8byte timestamp while parsing pkt + * If not configured, will result in L2 errors. + */ + pkind->hdr_sl = 4; + /* Adjust max packet length allowed */ + pkind->maxlen += (pkind->hdr_sl * 2); + bgx_config_timestamping(nic->node, bgx_idx, lmac, true); + nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7 | (1 << 3), + (ETYPE_ALG_ENDPARSE << 16) | ETH_P_1588); + } else if (!ptp->enable && pkind->hdr_sl) { + pkind->maxlen -= (pkind->hdr_sl * 2); + pkind->hdr_sl = 0; + bgx_config_timestamping(nic->node, bgx_idx, lmac, false); + nic_reg_write(nic, NIC_PF_RX_ETYPE_0_7 | (1 << 3), + (ETYPE_ALG_SKIP << 16) | ETH_P_8021Q); + } + + nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val); +} + /* Interrupt handler to handle mailbox messages from VFs */ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) { @@ -1022,6 +1069,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) case NIC_MBOX_MSG_PFC: nic_pause_frame(nic, vf, &mbx.pfc); goto unlock; + case NIC_MBOX_MSG_PTP_CFG: + nic_config_timestamp(nic, vf, &mbx.ptp); + break; default: dev_err(&nic->pdev->dev, "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg); diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h index 80d46337cf29..a16c48a1ebb2 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_reg.h +++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h @@ -99,6 +99,7 @@ #define NIC_PF_ECC3_DBE_INT_W1S (0x2708) #define NIC_PF_ECC3_DBE_ENA_W1C (0x2710) #define NIC_PF_ECC3_DBE_ENA_W1S (0x2718) +#define NIC_PF_INTFX_SEND_CFG (0x4000) #define NIC_PF_MCAM_0_191_ENA (0x100000) #define NIC_PF_MCAM_0_191_M_0_5_DATA (0x110000) #define NIC_PF_MCAM_CTRL (0x120000) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index b9ece9cbf98b..ed9f10bdf41e 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -9,12 +9,14 @@ /* ETHTOOL Support for VNIC_VF Device*/ #include +#include #include "nic_reg.h" #include "nic.h" #include "nicvf_queues.h" #include "q_struct.h" #include "thunder_bgx.h" +#include "../common/cavium_ptp.h" #define DRV_NAME "thunder-nicvf" #define DRV_VERSION "1.0" @@ -824,6 +826,31 @@ static int nicvf_set_pauseparam(struct net_device *dev, return 0; } +static int nicvf_get_ts_info(struct net_device *netdev, + struct ethtool_ts_info *info) +{ + struct nicvf *nic = netdev_priv(netdev); + + if (!nic->ptp_clock) + return ethtool_op_get_ts_info(netdev, info); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | + SOF_TIMESTAMPING_RX_SOFTWARE | + SOF_TIMESTAMPING_SOFTWARE | + SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | + SOF_TIMESTAMPING_RAW_HARDWARE; + + info->phc_index = cavium_ptp_clock_index(nic->ptp_clock); + + info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); + + info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) | + (1 << HWTSTAMP_FILTER_ALL); + + return 0; +} + static const struct ethtool_ops nicvf_ethtool_ops = { .get_link = nicvf_get_link, .get_drvinfo = nicvf_get_drvinfo, @@ -847,7 +874,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = { .set_channels = nicvf_set_channels, .get_pauseparam = nicvf_get_pauseparam, .set_pauseparam = nicvf_set_pauseparam, - .get_ts_info = ethtool_op_get_ts_info, + .get_ts_info = nicvf_get_ts_info, .get_link_ksettings = nicvf_get_link_ksettings, }; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 21618d0d694f..881af8a120f5 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -20,11 +20,13 @@ #include #include #include +#include #include "nic_reg.h" #include "nic.h" #include "nicvf_queues.h" #include "thunder_bgx.h" +#include "../common/cavium_ptp.h" #define DRV_NAME "thunder-nicvf" #define DRV_VERSION "1.0" @@ -602,6 +604,44 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog, return false; } +static void nicvf_snd_ptp_handler(struct net_device *netdev, + struct cqe_send_t *cqe_tx) +{ + struct nicvf *nic = netdev_priv(netdev); + struct skb_shared_hwtstamps ts; + u64 ns; + + nic = nic->pnicvf; + + /* Sync for 'ptp_skb' */ + smp_rmb(); + + /* New timestamp request can be queued now */ + atomic_set(&nic->tx_ptp_skbs, 0); + + /* Check for timestamp requested skb */ + if (!nic->ptp_skb) + return; + + /* Check if timestamping is timedout, which is set to 10us */ + if (cqe_tx->send_status == CQ_TX_ERROP_TSTMP_TIMEOUT || + cqe_tx->send_status == CQ_TX_ERROP_TSTMP_CONFLICT) + goto no_tstamp; + + /* Get the timestamp */ + memset(&ts, 0, sizeof(ts)); + ns = cavium_ptp_tstamp2time(nic->ptp_clock, cqe_tx->ptp_timestamp); + ts.hwtstamp = ns_to_ktime(ns); + skb_tstamp_tx(nic->ptp_skb, &ts); + +no_tstamp: + /* Free the original skb */ + dev_kfree_skb_any(nic->ptp_skb); + nic->ptp_skb = NULL; + /* Sync 'ptp_skb' */ + smp_wmb(); +} + static void nicvf_snd_pkt_handler(struct net_device *netdev, struct cqe_send_t *cqe_tx, int budget, int *subdesc_cnt, @@ -658,7 +698,12 @@ static void nicvf_snd_pkt_handler(struct net_device *netdev, prefetch(skb); (*tx_pkts)++; *tx_bytes += skb->len; - napi_consume_skb(skb, budget); + /* If timestamp is requested for this skb, don't free it */ + if (skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS && + !nic->pnicvf->ptp_skb) + nic->pnicvf->ptp_skb = skb; + else + napi_consume_skb(skb, budget); sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL; } else { /* In case of SW TSO on 88xx, only last segment will have @@ -697,6 +742,21 @@ static inline void nicvf_set_rxhash(struct net_device *netdev, skb_set_hash(skb, hash, hash_type); } +static inline void nicvf_set_rxtstamp(struct nicvf *nic, struct sk_buff *skb) +{ + u64 ns; + + if (!nic->ptp_clock || !nic->hw_rx_tstamp) + return; + + /* The first 8 bytes is the timestamp */ + ns = cavium_ptp_tstamp2time(nic->ptp_clock, + be64_to_cpu(*(__be64 *)skb->data)); + skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns); + + __skb_pull(skb, 8); +} + static void nicvf_rcv_pkt_handler(struct net_device *netdev, struct napi_struct *napi, struct cqe_rx_t *cqe_rx, @@ -748,6 +808,7 @@ static void nicvf_rcv_pkt_handler(struct net_device *netdev, return; } + nicvf_set_rxtstamp(nic, skb); nicvf_set_rxhash(netdev, cqe_rx, skb); skb_record_rx_queue(skb, rq_idx); @@ -823,10 +884,12 @@ static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx, &tx_pkts, &tx_bytes); tx_done++; break; + case CQE_TYPE_SEND_PTP: + nicvf_snd_ptp_handler(netdev, (void *)cq_desc); + break; case CQE_TYPE_INVALID: case CQE_TYPE_RX_SPLIT: case CQE_TYPE_RX_TCP: - case CQE_TYPE_SEND_PTP: /* Ignore for now */ break; } @@ -1322,12 +1385,28 @@ int nicvf_stop(struct net_device *netdev) nicvf_free_cq_poll(nic); + /* Free any pending SKB saved to receive timestamp */ + if (nic->ptp_skb) { + dev_kfree_skb_any(nic->ptp_skb); + nic->ptp_skb = NULL; + } + /* Clear multiqset info */ nic->pnicvf = nic; return 0; } +static int nicvf_config_hw_rx_tstamp(struct nicvf *nic, bool enable) +{ + union nic_mbx mbx = {}; + + mbx.ptp.msg = NIC_MBOX_MSG_PTP_CFG; + mbx.ptp.enable = enable; + + return nicvf_send_msg_to_pf(nic, &mbx); +} + static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu) { union nic_mbx mbx = {}; @@ -1397,6 +1476,12 @@ int nicvf_open(struct net_device *netdev) if (nic->sqs_mode) nicvf_get_primary_vf_struct(nic); + /* Configure PTP timestamp */ + if (nic->ptp_clock) + nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp); + atomic_set(&nic->tx_ptp_skbs, 0); + nic->ptp_skb = NULL; + /* Configure receive side scaling and MTU */ if (!nic->sqs_mode) { nicvf_rss_init(nic); @@ -1823,6 +1908,73 @@ static void nicvf_xdp_flush(struct net_device *dev) return; } +static int nicvf_config_hwtstamp(struct net_device *netdev, struct ifreq *ifr) +{ + struct hwtstamp_config config; + struct nicvf *nic = netdev_priv(netdev); + + if (!nic->ptp_clock) + return -ENODEV; + + if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) + return -EFAULT; + + /* reserved for future extensions */ + if (config.flags) + return -EINVAL; + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + case HWTSTAMP_TX_ON: + break; + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + nic->hw_rx_tstamp = false; + break; + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_SOME: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + nic->hw_rx_tstamp = true; + config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + + if (netif_running(netdev)) + nicvf_config_hw_rx_tstamp(nic, nic->hw_rx_tstamp); + + if (copy_to_user(ifr->ifr_data, &config, sizeof(config))) + return -EFAULT; + + return 0; +} + +static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) +{ + switch (cmd) { + case SIOCSHWTSTAMP: + return nicvf_config_hwtstamp(netdev, req); + default: + return -EOPNOTSUPP; + } +} + static const struct net_device_ops nicvf_netdev_ops = { .ndo_open = nicvf_open, .ndo_stop = nicvf_stop, @@ -1836,6 +1988,7 @@ static const struct net_device_ops nicvf_netdev_ops = { .ndo_bpf = nicvf_xdp, .ndo_xdp_xmit = nicvf_xdp_xmit, .ndo_xdp_flush = nicvf_xdp_flush, + .ndo_do_ioctl = nicvf_ioctl, }; static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -1845,6 +1998,16 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct nicvf *nic; int err, qcount; u16 sdevid; + struct cavium_ptp *ptp_clock; + + ptp_clock = cavium_ptp_get(); + if (IS_ERR(ptp_clock)) { + if (PTR_ERR(ptp_clock) == -ENODEV) + /* In virtualized environment we proceed without ptp */ + ptp_clock = NULL; + else + return PTR_ERR(ptp_clock); + } err = pci_enable_device(pdev); if (err) { @@ -1899,6 +2062,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) */ if (!nic->t88) nic->max_queues *= 2; + nic->ptp_clock = ptp_clock; /* MAP VF's configuration registers */ nic->reg_base = pcim_iomap(pdev, PCI_CFG_REG_BAR_NUM, 0); @@ -2012,6 +2176,7 @@ static void nicvf_remove(struct pci_dev *pdev) pci_set_drvdata(pdev, NULL); if (nic->drv_stats) free_percpu(nic->drv_stats); + cavium_ptp_put(nic->ptp_clock); free_netdev(netdev); pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 14e62c6ac342..3eae9ff9b53a 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -982,6 +982,9 @@ void nicvf_qset_config(struct nicvf *nic, bool enable) qs_cfg->be = 1; #endif qs_cfg->vnic = qs->vnic_id; + /* Enable Tx timestamping capability */ + if (nic->ptp_clock) + qs_cfg->send_tstmp_ena = 1; } nicvf_send_msg_to_pf(nic, &mbx); } @@ -1389,6 +1392,29 @@ nicvf_sq_add_hdr_subdesc(struct nicvf *nic, struct snd_queue *sq, int qentry, hdr->inner_l3_offset = skb_network_offset(skb) - 2; this_cpu_inc(nic->pnicvf->drv_stats->tx_tso); } + + /* Check if timestamp is requested */ + if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { + skb_tx_timestamp(skb); + return; + } + + /* Tx timestamping not supported along with TSO, so ignore request */ + if (skb_shinfo(skb)->gso_size) + return; + + /* HW supports only a single outstanding packet to timestamp */ + if (!atomic_add_unless(&nic->pnicvf->tx_ptp_skbs, 1, 1)) + return; + + /* Mark the SKB for later reference */ + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + + /* Finally enable timestamp generation + * Since 'post_cqe' is also set, two CQEs will be posted + * for this packet i.e CQE_TYPE_SEND and CQE_TYPE_SEND_PTP. + */ + hdr->tstmp = 1; } /* SQ GATHER subdescriptor diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 5e5c4d7796b8..0f23999c5bcf 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -245,6 +245,35 @@ void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable) } EXPORT_SYMBOL(bgx_lmac_rx_tx_enable); +/* Enables or disables timestamp insertion by BGX for Rx packets */ +void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable) +{ + struct bgx *bgx = get_bgx(node, bgx_idx); + struct lmac *lmac; + u64 csr_offset, cfg; + + if (!bgx) + return; + + lmac = &bgx->lmac[lmacid]; + + if (lmac->lmac_type == BGX_MODE_SGMII || + lmac->lmac_type == BGX_MODE_QSGMII || + lmac->lmac_type == BGX_MODE_RGMII) + csr_offset = BGX_GMP_GMI_RXX_FRM_CTL; + else + csr_offset = BGX_SMUX_RX_FRM_CTL; + + cfg = bgx_reg_read(bgx, lmacid, csr_offset); + + if (enable) + cfg |= BGX_PKT_RX_PTP_EN; + else + cfg &= ~BGX_PKT_RX_PTP_EN; + bgx_reg_write(bgx, lmacid, csr_offset, cfg); +} +EXPORT_SYMBOL(bgx_config_timestamping); + void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause) { struct pfc *pfc = (struct pfc *)pause; diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h index 23acdc5ab896..5a7567d31138 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h @@ -122,6 +122,8 @@ #define SPU_DBG_CTL_AN_NONCE_MCT_DIS BIT_ULL(29) #define BGX_SMUX_RX_INT 0x20000 +#define BGX_SMUX_RX_FRM_CTL 0x20020 +#define BGX_PKT_RX_PTP_EN BIT_ULL(12) #define BGX_SMUX_RX_JABBER 0x20030 #define BGX_SMUX_RX_CTL 0x20048 #define SMU_RX_CTL_STATUS (3ull << 0) @@ -172,6 +174,7 @@ #define GMI_PORT_CFG_SPEED_MSB BIT_ULL(8) #define GMI_PORT_CFG_RX_IDLE BIT_ULL(12) #define GMI_PORT_CFG_TX_IDLE BIT_ULL(13) +#define BGX_GMP_GMI_RXX_FRM_CTL 0x38028 #define BGX_GMP_GMI_RXX_JABBER 0x38038 #define BGX_GMP_GMI_TXX_THRESH 0x38210 #define BGX_GMP_GMI_TXX_APPEND 0x38218 @@ -223,6 +226,7 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac); void bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status); void bgx_lmac_internal_loopback(int node, int bgx_idx, int lmac_idx, bool enable); +void bgx_config_timestamping(int node, int bgx_idx, int lmacid, bool enable); void bgx_lmac_get_pfc(int node, int bgx_idx, int lmacid, void *pause); void bgx_lmac_set_pfc(int node, int bgx_idx, int lmacid, void *pause);