From patchwork Wed Jan 22 10:20:36 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Arinzon, David" X-Patchwork-Id: 13947120 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.190.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3B3C0145FE0 for ; Wed, 22 Jan 2025 10:21:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=207.171.190.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541267; cv=none; b=tJCdiRUS30G1Yyfa/vMONuujiWLaMF1fE3m+wPEAcxhoftgh8elUO2pXN/tc1+uvZ0QNnTw09aY64+PgF9QCKNncbZAyma6OJskoKG8BIvh228lnTubhLJF70Mtos8siKsjuL9iNMU7izwVT5ofjSr/d5Ab1wRNOBMl0eSAiJ7k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541267; c=relaxed/simple; bh=4r8oQSMLmjf8M11cR670jKu4n+M/ms/SL0IUyuJxwiM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=D/16hKGn+uFwV9nP9XcszW+nW4vO3V7RGx6YNV9IDf5N8590kUiQLRx8MJMX1mLUpeA22gbLp3l2wL0hCxStJMY6D9O1uzXjfttV6OBlIAH0bM/MpLB+ZdwDiMINbCeZ3SP7N4ul+3ZrTF9Yz+KI80nxYKHBfn3dPJR3Xq1QE1E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b=eHmWPrKM; arc=none smtp.client-ip=207.171.190.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="eHmWPrKM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1737541265; x=1769077265; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7z6YzoEzESWVNV5UIrlmMZdg7+uBB3iQponCQ/O2BEY=; b=eHmWPrKMCE8mFHTpfT8mhuoheeyYFpXxX0WUMMJozpN/b767UrIwxZZ7 Zz9lKMy9PSZr8Dp4dRbvvBksjS3wJzC3QoWrzOGlJ0dX1lwq83TWjsDyN s40hxo0tiGMRQI41La+X4JjfCOPGdidb0+Tzckfc4h/KQvQ1Vp1UiW7jp 4=; X-IronPort-AV: E=Sophos;i="6.13,224,1732579200"; d="scan'208";a="402617226" Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO smtpout.prod.us-west-2.prod.farcaster.email.amazon.dev) ([10.25.36.210]) by smtp-border-fw-33001.sea14.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2025 10:20:58 +0000 Received: from EX19MTAUWC002.ant.amazon.com [10.0.7.35:46314] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.54.33:2525] with esmtp (Farcaster) id 52edab7d-02e6-4f7f-b14c-e0a1b84f2041; Wed, 22 Jan 2025 10:20:58 +0000 (UTC) X-Farcaster-Flow-ID: 52edab7d-02e6-4f7f-b14c-e0a1b84f2041 Received: from EX19D010UWA003.ant.amazon.com (10.13.138.199) by EX19MTAUWC002.ant.amazon.com (10.250.64.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:20:55 +0000 Received: from EX19MTAUWB002.ant.amazon.com (10.250.64.231) by EX19D010UWA003.ant.amazon.com (10.13.138.199) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:20:55 +0000 Received: from email-imr-corp-prod-iad-all-1b-a03c1db8.us-east-1.amazon.com (10.25.36.214) by mail-relay.amazon.com (10.250.64.228) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39 via Frontend Transport; Wed, 22 Jan 2025 10:20:55 +0000 Received: from HFA15-G9FV5D3.amazon.com (unknown [10.85.143.175]) by email-imr-corp-prod-iad-all-1b-a03c1db8.us-east-1.amazon.com (Postfix) with ESMTP id 5820F80305; Wed, 22 Jan 2025 10:20:49 +0000 (UTC) From: David Arinzon To: David Miller , Jakub Kicinski , CC: David Arinzon , Eric Dumazet , Paolo Abeni , Richard Cochran , "Woodhouse, David" , "Machulsky, Zorik" , "Matushevsky, Alexander" , Saeed Bshara , "Wilson, Matt" , "Liguori, Anthony" , "Bshara, Nafea" , "Schmeilin, Evgeny" , "Belgazal, Netanel" , "Saidi, Ali" , "Herrenschmidt, Benjamin" , "Kiyanovski, Arthur" , "Dagan, Noam" , "Bernstein, Amit" , "Agroskin, Shay" , "Abboud, Osama" , "Ostrovsky, Evgeny" , "Tabachnik, Ofir" , "Machnikowski, Maciek" , "Rahul Rameshbabu" , Gal Pressman , "kernel test robot" Subject: [PATCH v5 net-next 1/5] net: ena: Add PHC support in the ENA driver Date: Wed, 22 Jan 2025 12:20:36 +0200 Message-ID: <20250122102040.752-2-darinzon@amazon.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250122102040.752-1-darinzon@amazon.com> References: <20250122102040.752-1-darinzon@amazon.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org The ENA driver will be extended to support the new PHC feature using ptp_clock interface [1]. this will provide timestamp reference for user space to allow measuring time offset between the PHC and the system clock in order to achieve nanosecond accuracy. [1] - https://www.kernel.org/doc/html/latest/driver-api/ptp.html Signed-off-by: Amit Bernstein Signed-off-by: David Arinzon Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202411020050.npvLNJ7N-lkp@intel.com Closes: https://lore.kernel.org/oe-kbuild-all/202411020715.L7KdiUt4-lkp@intel.com --- drivers/net/ethernet/amazon/Kconfig | 1 + drivers/net/ethernet/amazon/ena/Makefile | 2 +- .../net/ethernet/amazon/ena/ena_admin_defs.h | 63 ++++- drivers/net/ethernet/amazon/ena/ena_com.c | 247 ++++++++++++++++++ drivers/net/ethernet/amazon/ena/ena_com.h | 83 ++++++ drivers/net/ethernet/amazon/ena/ena_ethtool.c | 102 ++++++-- drivers/net/ethernet/amazon/ena/ena_netdev.c | 24 +- drivers/net/ethernet/amazon/ena/ena_netdev.h | 4 + drivers/net/ethernet/amazon/ena/ena_phc.c | 222 ++++++++++++++++ drivers/net/ethernet/amazon/ena/ena_phc.h | 37 +++ .../net/ethernet/amazon/ena/ena_regs_defs.h | 8 + 11 files changed, 769 insertions(+), 24 deletions(-) create mode 100644 drivers/net/ethernet/amazon/ena/ena_phc.c create mode 100644 drivers/net/ethernet/amazon/ena/ena_phc.h diff --git a/drivers/net/ethernet/amazon/Kconfig b/drivers/net/ethernet/amazon/Kconfig index c37fa393..8d61bc62 100644 --- a/drivers/net/ethernet/amazon/Kconfig +++ b/drivers/net/ethernet/amazon/Kconfig @@ -19,6 +19,7 @@ if NET_VENDOR_AMAZON config ENA_ETHERNET tristate "Elastic Network Adapter (ENA) support" depends on PCI_MSI && !CPU_BIG_ENDIAN + depends on PTP_1588_CLOCK_OPTIONAL select DIMLIB help This driver supports Elastic Network Adapter (ENA)" diff --git a/drivers/net/ethernet/amazon/ena/Makefile b/drivers/net/ethernet/amazon/ena/Makefile index 6ab61536..8c874177 100644 --- a/drivers/net/ethernet/amazon/ena/Makefile +++ b/drivers/net/ethernet/amazon/ena/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_ENA_ETHERNET) += ena.o -ena-y := ena_netdev.o ena_com.o ena_eth_com.o ena_ethtool.o ena_xdp.o +ena-y := ena_netdev.o ena_com.o ena_eth_com.o ena_ethtool.o ena_xdp.o ena_phc.o diff --git a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h index 9d9fa655..28770e60 100644 --- a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h +++ b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h @@ -60,6 +60,7 @@ enum ena_admin_aq_feature_id { ENA_ADMIN_AENQ_CONFIG = 26, ENA_ADMIN_LINK_CONFIG = 27, ENA_ADMIN_HOST_ATTR_CONFIG = 28, + ENA_ADMIN_PHC_CONFIG = 29, ENA_ADMIN_FEATURES_OPCODE_NUM = 32, }; @@ -127,6 +128,10 @@ enum ena_admin_get_stats_scope { ENA_ADMIN_ETH_TRAFFIC = 1, }; +enum ena_admin_phc_type { + ENA_ADMIN_PHC_TYPE_READLESS = 0, +}; + /* ENA SRD configuration for ENI */ enum ena_admin_ena_srd_flags { /* Feature enabled */ @@ -943,7 +948,9 @@ struct ena_admin_host_info { * 4 : rss_configurable_function_key * 5 : reserved * 6 : rx_page_reuse - * 31:7 : reserved + * 7 : reserved + * 8 : phc + * 31:9 : reserved */ u32 driver_supported_features; }; @@ -1023,6 +1030,43 @@ struct ena_admin_queue_ext_feature_desc { }; }; +struct ena_admin_feature_phc_desc { + /* PHC type as defined in enum ena_admin_get_phc_type, + * used only for GET command. + */ + u8 type; + + /* Reserved - MBZ */ + u8 reserved1[3]; + + /* PHC doorbell address as an offset to PCIe MMIO REG BAR, + * used only for GET command. + */ + u32 doorbell_offset; + + /* Max time for valid PHC retrieval, passing this threshold will + * fail the get-time request and block PHC requests for + * block_timeout_usec, used only for GET command. + */ + u32 expire_timeout_usec; + + /* PHC requests block period, blocking starts if PHC request expired + * in order to prevent floods on busy device, + * used only for GET command. + */ + u32 block_timeout_usec; + + /* Shared PHC physical address (ena_admin_phc_resp), + * used only for SET command. + */ + struct ena_common_mem_addr output_address; + + /* Shared PHC Size (ena_admin_phc_resp), + * used only for SET command. + */ + u32 output_length; +}; + struct ena_admin_get_feat_resp { struct ena_admin_acq_common_desc acq_common_desc; @@ -1052,6 +1096,8 @@ struct ena_admin_get_feat_resp { struct ena_admin_feature_intr_moder_desc intr_moderation; struct ena_admin_ena_hw_hints hw_hints; + + struct ena_admin_feature_phc_desc phc; } u; }; @@ -1085,6 +1131,9 @@ struct ena_admin_set_feat_cmd { /* LLQ configuration */ struct ena_admin_feature_llq_desc llq; + + /* PHC configuration */ + struct ena_admin_feature_phc_desc phc; } u; }; @@ -1162,6 +1211,16 @@ struct ena_admin_ena_mmio_req_read_less_resp { u32 reg_val; }; +struct ena_admin_phc_resp { + u16 req_id; + + u8 reserved1[6]; + + u64 timestamp; + + u8 reserved2[48]; +}; + /* aq_common_desc */ #define ENA_ADMIN_AQ_COMMON_DESC_COMMAND_ID_MASK GENMASK(11, 0) #define ENA_ADMIN_AQ_COMMON_DESC_PHASE_MASK BIT(0) @@ -1260,6 +1319,8 @@ struct ena_admin_ena_mmio_req_read_less_resp { #define ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK BIT(4) #define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_SHIFT 6 #define ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK BIT(6) +#define ENA_ADMIN_HOST_INFO_PHC_SHIFT 8 +#define ENA_ADMIN_HOST_INFO_PHC_MASK BIT(8) /* aenq_common_desc */ #define ENA_ADMIN_AENQ_COMMON_DESC_PHASE_MASK BIT(0) diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 66445617..c6b9939e 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -41,6 +41,12 @@ #define ENA_MAX_ADMIN_POLL_US 5000 +/* PHC definitions */ +#define ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC 10 +#define ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC 1000 +#define ENA_PHC_TIMESTAMP_ERROR 0xFFFFFFFFFFFFFFFF +#define ENA_PHC_REQ_ID_OFFSET 0xDEAD + /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ @@ -1641,6 +1647,247 @@ void ena_com_set_admin_polling_mode(struct ena_com_dev *ena_dev, bool polling) ena_dev->admin_queue.polling = polling; } +bool ena_com_phc_supported(struct ena_com_dev *ena_dev) +{ + return ena_com_check_supported_feature_id(ena_dev, ENA_ADMIN_PHC_CONFIG); +} + +int ena_com_phc_init(struct ena_com_dev *ena_dev) +{ + struct ena_com_phc_info *phc = &ena_dev->phc; + + memset(phc, 0x0, sizeof(*phc)); + + /* Allocate shared mem used PHC timestamp retrieved from device */ + phc->virt_addr = dma_alloc_coherent(ena_dev->dmadev, + sizeof(*phc->virt_addr), + &phc->phys_addr, + GFP_KERNEL); + if (unlikely(!phc->virt_addr)) + return -ENOMEM; + + spin_lock_init(&phc->lock); + + phc->virt_addr->req_id = 0; + phc->virt_addr->timestamp = 0; + + return 0; +} + +int ena_com_phc_config(struct ena_com_dev *ena_dev) +{ + struct ena_com_phc_info *phc = &ena_dev->phc; + struct ena_admin_get_feat_resp get_feat_resp; + struct ena_admin_set_feat_resp set_feat_resp; + struct ena_admin_set_feat_cmd set_feat_cmd; + int ret = 0; + + /* Get device PHC default configuration */ + ret = ena_com_get_feature(ena_dev, + &get_feat_resp, + ENA_ADMIN_PHC_CONFIG, + 0); + if (unlikely(ret)) { + netdev_err(ena_dev->net_device, + "Failed to get PHC feature configuration, error: %d\n", + ret); + return ret; + } + + /* Supporting only readless PHC retrieval */ + if (get_feat_resp.u.phc.type != ENA_ADMIN_PHC_TYPE_READLESS) { + netdev_err(ena_dev->net_device, "Unsupported PHC type, error: %d\n", + -EOPNOTSUPP); + return -EOPNOTSUPP; + } + + /* Update PHC doorbell offset according to device value, + * used to write req_id to PHC bar + */ + phc->doorbell_offset = get_feat_resp.u.phc.doorbell_offset; + + /* Update PHC expire timeout according to device + * or default driver value + */ + phc->expire_timeout_usec = (get_feat_resp.u.phc.expire_timeout_usec) ? + get_feat_resp.u.phc.expire_timeout_usec : + ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC; + + /* Update PHC block timeout according to device + * or default driver value + */ + phc->block_timeout_usec = (get_feat_resp.u.phc.block_timeout_usec) ? + get_feat_resp.u.phc.block_timeout_usec : + ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC; + + /* Sanity check - expire timeout must not be above skip timeout */ + if (phc->expire_timeout_usec > phc->block_timeout_usec) + phc->expire_timeout_usec = phc->block_timeout_usec; + + /* Prepare PHC config feature command */ + memset(&set_feat_cmd, 0x0, sizeof(set_feat_cmd)); + set_feat_cmd.aq_common_descriptor.opcode = ENA_ADMIN_SET_FEATURE; + set_feat_cmd.feat_common.feature_id = ENA_ADMIN_PHC_CONFIG; + set_feat_cmd.u.phc.output_length = sizeof(*phc->virt_addr); + ret = ena_com_mem_addr_set(ena_dev, + &set_feat_cmd.u.phc.output_address, + phc->phys_addr); + if (unlikely(ret)) { + netdev_err(ena_dev->net_device, "Failed setting PHC output address, error: %d\n", + ret); + return ret; + } + + /* Send PHC feature command to the device */ + ret = ena_com_execute_admin_command(&ena_dev->admin_queue, + (struct ena_admin_aq_entry *)&set_feat_cmd, + sizeof(set_feat_cmd), + (struct ena_admin_acq_entry *)&set_feat_resp, + sizeof(set_feat_resp)); + + if (unlikely(ret)) { + netdev_err(ena_dev->net_device, + "Failed to enable PHC, error: %d\n", + ret); + return ret; + } + + phc->active = true; + netdev_dbg(ena_dev->net_device, "PHC is active in the device\n"); + + return ret; +} + +void ena_com_phc_destroy(struct ena_com_dev *ena_dev) +{ + struct ena_com_phc_info *phc = &ena_dev->phc; + unsigned long flags = 0; + + /* In case PHC is not supported by the device, silently exiting */ + if (!phc->virt_addr) + return; + + spin_lock_irqsave(&phc->lock, flags); + phc->active = false; + spin_unlock_irqrestore(&phc->lock, flags); + + dma_free_coherent(ena_dev->dmadev, + sizeof(*phc->virt_addr), + phc->virt_addr, + phc->phys_addr); + phc->virt_addr = NULL; +} + +int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) +{ + volatile struct ena_admin_phc_resp *read_resp = ena_dev->phc.virt_addr; + const ktime_t zero_system_time = ktime_set(0, 0); + struct ena_com_phc_info *phc = &ena_dev->phc; + ktime_t expire_time; + ktime_t block_time; + unsigned long flags = 0; + int ret = 0; + + if (!phc->active) { + netdev_err(ena_dev->net_device, "PHC feature is not active in the device\n"); + return -EOPNOTSUPP; + } + + spin_lock_irqsave(&phc->lock, flags); + + /* Check if PHC is in blocked state */ + if (unlikely(ktime_compare(phc->system_time, zero_system_time))) { + /* Check if blocking time expired */ + block_time = ktime_add_us(phc->system_time, phc->block_timeout_usec); + if (!ktime_after(ktime_get(), block_time)) { + /* PHC is still in blocked state, skip PHC request */ + phc->stats.phc_skp++; + ret = -EBUSY; + goto skip; + } + + /* PHC is in active state, update statistics according to + * req_id and timestamp + */ + if ((READ_ONCE(read_resp->req_id) != phc->req_id) || + read_resp->timestamp == ENA_PHC_TIMESTAMP_ERROR) + /* Device didn't update req_id during blocking time + * or timestamp is invalid, this indicates on a + * device error + */ + phc->stats.phc_err++; + else + /* Device updated req_id during blocking time + * with valid timestamp + */ + phc->stats.phc_exp++; + } + + /* Setting relative timeouts */ + phc->system_time = ktime_get(); + block_time = ktime_add_us(phc->system_time, phc->block_timeout_usec); + expire_time = ktime_add_us(phc->system_time, phc->expire_timeout_usec); + + /* We expect the device to return this req_id once + * the new PHC timestamp is updated + */ + phc->req_id++; + + /* Initialize PHC shared memory with different req_id value + * to be able to identify once the device changes it to req_id + */ + read_resp->req_id = phc->req_id + ENA_PHC_REQ_ID_OFFSET; + + /* Writing req_id to PHC bar */ + writel(phc->req_id, ena_dev->reg_bar + phc->doorbell_offset); + + /* Stalling until the device updates req_id */ + while (1) { + if (unlikely(ktime_after(ktime_get(), expire_time))) { + /* Gave up waiting for updated req_id, + * PHC enters into blocked state until passing + * blocking time + */ + ret = -EBUSY; + break; + } + + /* Check if req_id was updated by the device */ + if (READ_ONCE(read_resp->req_id) != phc->req_id) { + /* req_id was not updated by the device, + * check again on next loop + */ + continue; + } + + /* req_id was updated which indicates that PHC timestamp + * was updated too + */ + *timestamp = read_resp->timestamp; + + /* PHC timestamp validty check */ + if (unlikely(*timestamp == ENA_PHC_TIMESTAMP_ERROR)) { + /* Retrieved invalid PHC timestamp, PHC enters into + * blocked state until passing blocking time + */ + ret = -EBUSY; + break; + } + + /* Retrieved valid PHC timestamp */ + phc->stats.phc_cnt++; + + /* This indicates PHC state is active */ + phc->system_time = zero_system_time; + break; + } + +skip: + spin_unlock_irqrestore(&phc->lock, flags); + + return ret; +} + int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev) { struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h b/drivers/net/ethernet/amazon/ena/ena_com.h index 9414e93d..3905d348 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.h +++ b/drivers/net/ethernet/amazon/ena/ena_com.h @@ -210,6 +210,13 @@ struct ena_com_stats_admin { u64 no_completion; }; +struct ena_com_stats_phc { + u64 phc_cnt; + u64 phc_exp; + u64 phc_skp; + u64 phc_err; +}; + struct ena_com_admin_queue { void *q_dmadev; struct ena_com_dev *ena_dev; @@ -258,6 +265,47 @@ struct ena_com_mmio_read { spinlock_t lock; }; +/* PTP hardware clock (PHC) MMIO read data info */ +struct ena_com_phc_info { + /* Internal PHC statistics */ + struct ena_com_stats_phc stats; + + /* PHC shared memory - virtual address */ + struct ena_admin_phc_resp *virt_addr; + + /* System time of last PHC request */ + ktime_t system_time; + + /* Spin lock to ensure a single outstanding PHC read */ + spinlock_t lock; + + /* PHC doorbell address as an offset to PCIe MMIO REG BAR */ + u32 doorbell_offset; + + /* Shared memory read expire timeout (usec) + * Max time for valid PHC retrieval, passing this threshold will fail + * the get time request and block new PHC requests for block_timeout_usec + * in order to prevent floods on busy device + */ + u32 expire_timeout_usec; + + /* Shared memory read abort timeout (usec) + * PHC requests block period, blocking starts once PHC request expired + * in order to prevent floods on busy device, + * any PHC requests during block period will be skipped + */ + u32 block_timeout_usec; + + /* PHC shared memory - physical address */ + dma_addr_t phys_addr; + + /* Request id sent to the device */ + u16 req_id; + + /* True if PHC is active in the device */ + bool active; +}; + struct ena_rss { /* Indirect table */ u16 *host_rss_ind_tbl; @@ -317,6 +365,7 @@ struct ena_com_dev { u32 ena_min_poll_delay_us; struct ena_com_mmio_read mmio_read; + struct ena_com_phc_info phc; struct ena_rss rss; u32 supported_features; @@ -382,6 +431,40 @@ struct ena_aenq_handlers { */ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev); +/* ena_com_phc_init - Allocate and initialize PHC feature + * @ena_dev: ENA communication layer struct + * @note: This method assumes PHC is supported by the device + * @return - 0 on success, negative value on failure + */ +int ena_com_phc_init(struct ena_com_dev *ena_dev); + +/* ena_com_phc_supported - Return if PHC feature is supported by the device + * @ena_dev: ENA communication layer struct + * @note: This method must be called after getting supported features + * @return - supported or not + */ +bool ena_com_phc_supported(struct ena_com_dev *ena_dev); + +/* ena_com_phc_config - Configure PHC feature + * @ena_dev: ENA communication layer struct + * Configure PHC feature in driver and device + * @note: This method assumes PHC is supported by the device + * @return - 0 on success, negative value on failure + */ +int ena_com_phc_config(struct ena_com_dev *ena_dev); + +/* ena_com_phc_destroy - Destroy PHC feature + * @ena_dev: ENA communication layer struct + */ +void ena_com_phc_destroy(struct ena_com_dev *ena_dev); + +/* ena_com_phc_get - Retrieve PHC timestamp + * @ena_dev: ENA communication layer struct + * @timestamp: Retrieve PHC timestamp + * @return - 0 on success, negative value on failure + */ +int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp); + /* ena_com_set_mmio_read_mode - Enable/disable the indirect mmio reg read mechanism * @ena_dev: ENA communication layer struct * @readless_supported: readless mode (enable/disable) diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index a3c934c3..47c07534 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -5,9 +5,11 @@ #include #include +#include #include "ena_netdev.h" #include "ena_xdp.h" +#include "ena_phc.h" struct ena_stats { char name[ETH_GSTRING_LEN]; @@ -18,11 +20,16 @@ struct ena_hw_metrics { char name[ETH_GSTRING_LEN]; }; -#define ENA_STAT_ENA_COM_ENTRY(stat) { \ +#define ENA_STAT_ENA_COM_ADMIN_ENTRY(stat) { \ .name = #stat, \ .stat_offset = offsetof(struct ena_com_stats_admin, stat) / sizeof(u64) \ } +#define ENA_STAT_ENA_COM_PHC_ENTRY(stat) { \ + .name = #stat, \ + .stat_offset = offsetof(struct ena_com_stats_phc, stat) / sizeof(u64) \ +} + #define ENA_STAT_ENTRY(stat, stat_type) { \ .name = #stat, \ .stat_offset = offsetof(struct ena_stats_##stat_type, stat) / sizeof(u64) \ @@ -136,18 +143,26 @@ static const struct ena_stats ena_stats_rx_strings[] = { ENA_STAT_RX_ENTRY(xdp_redirect), }; -static const struct ena_stats ena_stats_ena_com_strings[] = { - ENA_STAT_ENA_COM_ENTRY(aborted_cmd), - ENA_STAT_ENA_COM_ENTRY(submitted_cmd), - ENA_STAT_ENA_COM_ENTRY(completed_cmd), - ENA_STAT_ENA_COM_ENTRY(out_of_space), - ENA_STAT_ENA_COM_ENTRY(no_completion), +static const struct ena_stats ena_stats_ena_com_admin_strings[] = { + ENA_STAT_ENA_COM_ADMIN_ENTRY(aborted_cmd), + ENA_STAT_ENA_COM_ADMIN_ENTRY(submitted_cmd), + ENA_STAT_ENA_COM_ADMIN_ENTRY(completed_cmd), + ENA_STAT_ENA_COM_ADMIN_ENTRY(out_of_space), + ENA_STAT_ENA_COM_ADMIN_ENTRY(no_completion), +}; + +static const struct ena_stats ena_stats_ena_com_phc_strings[] = { + ENA_STAT_ENA_COM_PHC_ENTRY(phc_cnt), + ENA_STAT_ENA_COM_PHC_ENTRY(phc_exp), + ENA_STAT_ENA_COM_PHC_ENTRY(phc_skp), + ENA_STAT_ENA_COM_PHC_ENTRY(phc_err), }; #define ENA_STATS_ARRAY_GLOBAL ARRAY_SIZE(ena_stats_global_strings) #define ENA_STATS_ARRAY_TX ARRAY_SIZE(ena_stats_tx_strings) #define ENA_STATS_ARRAY_RX ARRAY_SIZE(ena_stats_rx_strings) -#define ENA_STATS_ARRAY_ENA_COM ARRAY_SIZE(ena_stats_ena_com_strings) +#define ENA_STATS_ARRAY_ENA_COM_ADMIN ARRAY_SIZE(ena_stats_ena_com_admin_strings) +#define ENA_STATS_ARRAY_ENA_COM_PHC ARRAY_SIZE(ena_stats_ena_com_phc_strings) #define ENA_STATS_ARRAY_ENI ARRAY_SIZE(ena_stats_eni_strings) #define ENA_STATS_ARRAY_ENA_SRD ARRAY_SIZE(ena_srd_info_strings) #define ENA_METRICS_ARRAY_ENI ARRAY_SIZE(ena_hw_stats_strings) @@ -250,14 +265,14 @@ static void ena_queue_stats(struct ena_adapter *adapter, u64 **data) } } -static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data) +static void ena_get_admin_queue_stats(struct ena_adapter *adapter, u64 **data) { const struct ena_stats *ena_stats; u64 *ptr; int i; - for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) { - ena_stats = &ena_stats_ena_com_strings[i]; + for (i = 0; i < ENA_STATS_ARRAY_ENA_COM_ADMIN; i++) { + ena_stats = &ena_stats_ena_com_admin_strings[i]; ptr = (u64 *)&adapter->ena_dev->admin_queue.stats + ena_stats->stat_offset; @@ -266,6 +281,19 @@ static void ena_dev_admin_queue_stats(struct ena_adapter *adapter, u64 **data) } } +static void ena_get_phc_stats(struct ena_adapter *adapter, u64 **data) +{ + const struct ena_stats *ena_stats; + u64 *ptr; + int i; + + for (i = 0; i < ENA_STATS_ARRAY_ENA_COM_PHC; i++) { + ena_stats = &ena_stats_ena_com_phc_strings[i]; + ptr = (u64 *)&adapter->ena_dev->phc.stats + ena_stats->stat_offset; + *(*data)++ = *ptr; + } +} + static void ena_get_stats(struct ena_adapter *adapter, u64 *data, bool hw_stats_needed) @@ -286,7 +314,10 @@ static void ena_get_stats(struct ena_adapter *adapter, ena_metrics_stats(adapter, &data); ena_queue_stats(adapter, &data); - ena_dev_admin_queue_stats(adapter, &data); + ena_get_admin_queue_stats(adapter, &data); + + if (ena_phc_is_active(adapter)) + ena_get_phc_stats(adapter, &data); } static void ena_get_ethtool_stats(struct net_device *netdev, @@ -298,11 +329,28 @@ static void ena_get_ethtool_stats(struct net_device *netdev, ena_get_stats(adapter, data, true); } +static int ena_get_ts_info(struct net_device *netdev, + struct kernel_ethtool_ts_info *info) +{ + struct ena_adapter *adapter = netdev_priv(netdev); + + info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE; + + info->phc_index = ena_phc_get_index(adapter); + + return 0; +} + static int ena_get_sw_stats_count(struct ena_adapter *adapter) { - return adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) - + adapter->xdp_num_queues * ENA_STATS_ARRAY_TX - + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM; + int count = adapter->num_io_queues * (ENA_STATS_ARRAY_TX + ENA_STATS_ARRAY_RX) + + adapter->xdp_num_queues * ENA_STATS_ARRAY_TX + + ENA_STATS_ARRAY_GLOBAL + ENA_STATS_ARRAY_ENA_COM_ADMIN; + + if (ena_phc_is_active(adapter)) + count += ENA_STATS_ARRAY_ENA_COM_PHC; + + return count; } static int ena_get_hw_stats_count(struct ena_adapter *adapter) @@ -392,19 +440,30 @@ static void ena_queue_strings(struct ena_adapter *adapter, u8 **data) } } -static void ena_com_dev_strings(u8 **data) +static void ena_get_admin_strings(u8 **data) { const struct ena_stats *ena_stats; int i; - for (i = 0; i < ENA_STATS_ARRAY_ENA_COM; i++) { - ena_stats = &ena_stats_ena_com_strings[i]; + for (i = 0; i < ENA_STATS_ARRAY_ENA_COM_ADMIN; i++) { + ena_stats = &ena_stats_ena_com_admin_strings[i]; ethtool_sprintf(data, "ena_admin_q_%s", ena_stats->name); } } +static void ena_get_phc_strings(u8 **data) +{ + const struct ena_stats *ena_stats; + int i; + + for (i = 0; i < ENA_STATS_ARRAY_ENA_COM_PHC; i++) { + ena_stats = &ena_stats_ena_com_phc_strings[i]; + ethtool_puts(data, ena_stats->name); + } +} + static void ena_get_strings(struct ena_adapter *adapter, u8 *data, bool hw_stats_needed) @@ -421,7 +480,10 @@ static void ena_get_strings(struct ena_adapter *adapter, ena_metrics_stats_strings(adapter, &data); ena_queue_strings(adapter, &data); - ena_com_dev_strings(&data); + ena_get_admin_strings(&data); + + if (ena_phc_is_active(adapter)) + ena_get_phc_strings(&data); } static void ena_get_ethtool_strings(struct net_device *netdev, @@ -1107,7 +1169,7 @@ static const struct ethtool_ops ena_ethtool_ops = { .set_channels = ena_set_channels, .get_tunable = ena_get_tunable, .set_tunable = ena_set_tunable, - .get_ts_info = ethtool_op_get_ts_info, + .get_ts_info = ena_get_ts_info, }; void ena_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index c1295dfa..13c9d93e 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -22,6 +22,8 @@ #include "ena_pci_id_tbl.h" #include "ena_xdp.h" +#include "ena_phc.h" + MODULE_AUTHOR("Amazon.com, Inc. or its affiliates"); MODULE_DESCRIPTION(DEVICE_NAME); MODULE_LICENSE("GPL"); @@ -2773,7 +2775,8 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pd ENA_ADMIN_HOST_INFO_INTERRUPT_MODERATION_MASK | ENA_ADMIN_HOST_INFO_RX_BUF_MIRRORING_MASK | ENA_ADMIN_HOST_INFO_RSS_CONFIGURABLE_FUNCTION_KEY_MASK | - ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK; + ENA_ADMIN_HOST_INFO_RX_PAGE_REUSE_MASK | + ENA_ADMIN_HOST_INFO_PHC_MASK; rc = ena_com_set_host_attributes(ena_dev); if (rc) { @@ -3218,6 +3221,10 @@ static int ena_device_init(struct ena_adapter *adapter, struct pci_dev *pdev, if (unlikely(rc)) goto err_admin_init; + rc = ena_phc_init(adapter); + if (unlikely(rc && (rc != -EOPNOTSUPP))) + netdev_err(netdev, "Failed initializing PHC, error: %d\n", rc); + return 0; err_admin_init: @@ -3301,6 +3308,8 @@ static int ena_destroy_device(struct ena_adapter *adapter, bool graceful) ena_com_admin_destroy(ena_dev); + ena_phc_destroy(adapter); + ena_com_mmio_reg_read_request_destroy(ena_dev); /* return reset reason to default value */ @@ -3374,6 +3383,7 @@ err_device_destroy: ena_com_wait_for_abort_completion(ena_dev); ena_com_admin_destroy(ena_dev); ena_com_dev_reset(ena_dev, ENA_REGS_RESET_DRIVER_INVALID_STATE); + ena_phc_destroy(adapter); ena_com_mmio_reg_read_request_destroy(ena_dev); err: clear_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags); @@ -3961,10 +3971,16 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_drvdata(pdev, adapter); + rc = ena_phc_alloc(adapter); + if (rc) { + netdev_err(netdev, "ena_phc_alloc failed\n"); + goto err_netdev_destroy; + } + rc = ena_com_allocate_customer_metrics_buffer(ena_dev); if (rc) { netdev_err(netdev, "ena_com_allocate_customer_metrics_buffer failed\n"); - goto err_netdev_destroy; + goto err_free_phc; } rc = ena_map_llq_mem_bar(pdev, ena_dev, bars); @@ -4101,6 +4117,8 @@ err_device_destroy: ena_com_admin_destroy(ena_dev); err_metrics_destroy: ena_com_delete_customer_metrics_buffer(ena_dev); +err_free_phc: + ena_phc_free(adapter); err_netdev_destroy: free_netdev(netdev); err_free_region: @@ -4148,6 +4166,8 @@ static void __ena_shutoff(struct pci_dev *pdev, bool shutdown) adapter->reset_reason = ENA_REGS_RESET_SHUTDOWN; ena_destroy_device(adapter, true); + ena_phc_free(adapter); + if (shutdown) { netif_device_detach(netdev); dev_close(netdev); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 6e12ae3b..7867cd7f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -110,6 +110,8 @@ #define ENA_MMIO_DISABLE_REG_READ BIT(0) +struct ena_phc_info; + struct ena_irq { irq_handler_t handler; void *data; @@ -348,6 +350,8 @@ struct ena_adapter { char name[ENA_NAME_MAX_LEN]; + struct ena_phc_info *phc_info; + unsigned long flags; /* TX */ struct ena_ring tx_ring[ENA_MAX_NUM_IO_QUEUES] diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.c b/drivers/net/ethernet/amazon/ena/ena_phc.c new file mode 100644 index 00000000..87495de0 --- /dev/null +++ b/drivers/net/ethernet/amazon/ena/ena_phc.c @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright 2015-2022 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#include +#include "ena_netdev.h" +#include "ena_phc.h" + +static int ena_phc_adjtime(struct ptp_clock_info *clock_info, s64 delta) +{ + return -EOPNOTSUPP; +} + +static int ena_phc_adjfine(struct ptp_clock_info *clock_info, long scaled_ppm) +{ + return -EOPNOTSUPP; +} + +static int ena_phc_feature_enable(struct ptp_clock_info *clock_info, + struct ptp_clock_request *rq, + int on) +{ + return -EOPNOTSUPP; +} + +static int ena_phc_gettimex64(struct ptp_clock_info *clock_info, + struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct ena_phc_info *phc_info = + container_of(clock_info, struct ena_phc_info, clock_info); + unsigned long flags; + u64 timestamp_nsec; + int rc; + + spin_lock_irqsave(&phc_info->lock, flags); + + ptp_read_system_prets(sts); + + rc = ena_com_phc_get(phc_info->adapter->ena_dev, ×tamp_nsec); + + ptp_read_system_postts(sts); + + spin_unlock_irqrestore(&phc_info->lock, flags); + + *ts = ns_to_timespec64(timestamp_nsec); + + return rc; +} + +static int ena_phc_settime64(struct ptp_clock_info *clock_info, + const struct timespec64 *ts) +{ + return -EOPNOTSUPP; +} + +static struct ptp_clock_info ena_ptp_clock_info = { + .owner = THIS_MODULE, + .n_alarm = 0, + .n_ext_ts = 0, + .n_per_out = 0, + .pps = 0, + .adjtime = ena_phc_adjtime, + .adjfine = ena_phc_adjfine, + .gettimex64 = ena_phc_gettimex64, + .settime64 = ena_phc_settime64, + .enable = ena_phc_feature_enable, +}; + +/* Enable/Disable PHC by the kernel, affects on the next init flow */ +void ena_phc_enable(struct ena_adapter *adapter, bool enable) +{ + struct ena_phc_info *phc_info = adapter->phc_info; + + if (!phc_info) { + netdev_err(adapter->netdev, "phc_info is not allocated\n"); + return; + } + + phc_info->enabled = enable; +} + +/* Check if PHC is enabled by the kernel */ +bool ena_phc_is_enabled(struct ena_adapter *adapter) +{ + struct ena_phc_info *phc_info = adapter->phc_info; + + return (phc_info && phc_info->enabled); +} + +/* PHC is activated if ptp clock is registered in the kernel */ +bool ena_phc_is_active(struct ena_adapter *adapter) +{ + struct ena_phc_info *phc_info = adapter->phc_info; + + return (phc_info && phc_info->clock); +} + +static int ena_phc_register(struct ena_adapter *adapter) +{ + struct pci_dev *pdev = adapter->pdev; + struct ptp_clock_info *clock_info; + struct ena_phc_info *phc_info; + int rc = 0; + + phc_info = adapter->phc_info; + clock_info = &phc_info->clock_info; + + phc_info->adapter = adapter; + + spin_lock_init(&phc_info->lock); + + /* Fill the ptp_clock_info struct and register PTP clock */ + *clock_info = ena_ptp_clock_info; + snprintf(clock_info->name, + sizeof(clock_info->name), + "ena-ptp-%02x", + PCI_SLOT(pdev->devfn)); + + phc_info->clock = ptp_clock_register(clock_info, &pdev->dev); + if (IS_ERR(phc_info->clock)) { + rc = PTR_ERR(phc_info->clock); + netdev_err(adapter->netdev, "Failed registering ptp clock, error: %d\n", + rc); + phc_info->clock = NULL; + } + + return rc; +} + +static void ena_phc_unregister(struct ena_adapter *adapter) +{ + struct ena_phc_info *phc_info = adapter->phc_info; + + if (ena_phc_is_active(adapter)) { + ptp_clock_unregister(phc_info->clock); + phc_info->clock = NULL; + } +} + +int ena_phc_alloc(struct ena_adapter *adapter) +{ + /* Allocate driver specific PHC info */ + adapter->phc_info = vzalloc(sizeof(*adapter->phc_info)); + if (unlikely(!adapter->phc_info)) { + netdev_err(adapter->netdev, "Failed to alloc phc_info\n"); + return -ENOMEM; + } + + return 0; +} + +void ena_phc_free(struct ena_adapter *adapter) +{ + if (adapter->phc_info) { + vfree(adapter->phc_info); + adapter->phc_info = NULL; + } +} + +int ena_phc_init(struct ena_adapter *adapter) +{ + struct ena_com_dev *ena_dev = adapter->ena_dev; + struct net_device *netdev = adapter->netdev; + int rc = -EOPNOTSUPP; + + /* Validate PHC feature is supported in the device */ + if (!ena_com_phc_supported(ena_dev)) { + netdev_dbg(netdev, "PHC feature is not supported by the device\n"); + goto err_ena_com_phc_init; + } + + /* Validate PHC feature is enabled by the kernel */ + if (!ena_phc_is_enabled(adapter)) { + netdev_dbg(netdev, "PHC feature is not enabled by the kernel\n"); + goto err_ena_com_phc_init; + } + + /* Initialize device specific PHC info */ + rc = ena_com_phc_init(ena_dev); + if (unlikely(rc)) { + netdev_err(netdev, "Failed to init phc, error: %d\n", rc); + goto err_ena_com_phc_init; + } + + /* Configure PHC feature in driver and device */ + rc = ena_com_phc_config(ena_dev); + if (unlikely(rc)) { + netdev_err(netdev, "Failed to config phc, error: %d\n", rc); + goto err_ena_com_phc_config; + } + + /* Register to PTP class driver */ + rc = ena_phc_register(adapter); + if (unlikely(rc)) { + netdev_err(netdev, "Failed to register phc, error: %d\n", rc); + goto err_ena_com_phc_config; + } + + return 0; + +err_ena_com_phc_config: + ena_com_phc_destroy(ena_dev); +err_ena_com_phc_init: + ena_phc_enable(adapter, false); + return rc; +} + +void ena_phc_destroy(struct ena_adapter *adapter) +{ + ena_phc_unregister(adapter); + ena_com_phc_destroy(adapter->ena_dev); +} + +int ena_phc_get_index(struct ena_adapter *adapter) +{ + if (ena_phc_is_active(adapter)) + return ptp_clock_index(adapter->phc_info->clock); + + return -1; +} diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.h b/drivers/net/ethernet/amazon/ena/ena_phc.h new file mode 100644 index 00000000..7364fe71 --- /dev/null +++ b/drivers/net/ethernet/amazon/ena/ena_phc.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright 2015-2022 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#ifndef ENA_PHC_H +#define ENA_PHC_H + +#include + +struct ena_phc_info { + /* PTP hardware capabilities */ + struct ptp_clock_info clock_info; + + /* Registered PTP clock device */ + struct ptp_clock *clock; + + /* Adapter specific private data structure */ + struct ena_adapter *adapter; + + /* PHC lock */ + spinlock_t lock; + + /* Enabled by kernel */ + bool enabled; +}; + +void ena_phc_enable(struct ena_adapter *adapter, bool enable); +bool ena_phc_is_enabled(struct ena_adapter *adapter); +bool ena_phc_is_active(struct ena_adapter *adapter); +int ena_phc_get_index(struct ena_adapter *adapter); +int ena_phc_init(struct ena_adapter *adapter); +void ena_phc_destroy(struct ena_adapter *adapter); +int ena_phc_alloc(struct ena_adapter *adapter); +void ena_phc_free(struct ena_adapter *adapter); + +#endif /* ENA_PHC_H */ diff --git a/drivers/net/ethernet/amazon/ena/ena_regs_defs.h b/drivers/net/ethernet/amazon/ena/ena_regs_defs.h index a2efebaf..51068dc1 100644 --- a/drivers/net/ethernet/amazon/ena/ena_regs_defs.h +++ b/drivers/net/ethernet/amazon/ena/ena_regs_defs.h @@ -53,6 +53,11 @@ enum ena_regs_reset_reason_types { #define ENA_REGS_MMIO_RESP_HI_OFF 0x64 #define ENA_REGS_RSS_IND_ENTRY_UPDATE_OFF 0x68 +/* phc_registers offsets */ + +/* 100 base */ +#define ENA_REGS_PHC_DB_OFF 0x100 + /* version register */ #define ENA_REGS_VERSION_MINOR_VERSION_MASK 0xff #define ENA_REGS_VERSION_MAJOR_VERSION_SHIFT 8 @@ -129,4 +134,7 @@ enum ena_regs_reset_reason_types { #define ENA_REGS_RSS_IND_ENTRY_UPDATE_CQ_IDX_SHIFT 16 #define ENA_REGS_RSS_IND_ENTRY_UPDATE_CQ_IDX_MASK 0xffff0000 +/* phc_db_req_id register */ +#define ENA_REGS_PHC_DB_REQ_ID_MASK 0xffff + #endif /* _ENA_REGS_H_ */ From patchwork Wed Jan 22 10:20:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "Arinzon, David" X-Patchwork-Id: 13947122 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp-fw-52005.amazon.com (smtp-fw-52005.amazon.com [52.119.213.156]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB127211283 for ; Wed, 22 Jan 2025 10:21:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.119.213.156 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541282; cv=none; b=cY+KLrdLfRpCZ1Tv324ccpUokK4velu2ls5m1BKVZAAVfY1e87Qo3xpgU+2vZ545VXfQBkZb5/8DHuN/G+fQL653Q4WnugLpAaK71NivlKtESghv5HiPa7hg2N1NW8JwZ4dHkpwPA0B6Y3zykwbp0cu6eaywITubnMeCLDSHO7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541282; c=relaxed/simple; bh=ed9jDh1RZMUcjVuVJhtdbA94/YBw7AVsAWDRx4bzjTY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=f+oqwU01VdBBO5ytNGcytfrs2VKNovIaevbW/OK8VpVgyz6YWeq0wUzdgy9w+tB2pgYaXR2a39sPgzKrQ392JvWZ8MmsyAibQ5kGi6avzHPFKZ4/mZBqqsT8Ff69DAk+wGLKvQCT3AispIbq4dzqh3YyQGxnXfUc0qPN6UolGa8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b=N7+p/p0B; arc=none smtp.client-ip=52.119.213.156 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="N7+p/p0B" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1737541281; x=1769077281; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gyyUiNpAZSUmgse4Aa6uYYacZ1ezoWiBCciLzWe8gmk=; b=N7+p/p0BOzMWOwnpjdrY8fAF1a5Bb5a7wQySHJhp0IKhbPSRNevwAT0W ZiKRcO7I3qRCXFstIdtY+wKX17tLszneBoe+RI3h0imkIU79Vm8k5rQtt OiFWyIsdmQR4xI814LOEzFlQLeSChrEFhB4yW7LDX4dD+DpwJ6iTJ+43k Q=; X-IronPort-AV: E=Sophos;i="6.13,224,1732579200"; d="scan'208";a="712670962" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO smtpout.prod.us-west-2.prod.farcaster.email.amazon.dev) ([10.43.8.6]) by smtp-border-fw-52005.iad7.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2025 10:21:16 +0000 Received: from EX19MTAUWB002.ant.amazon.com [10.0.7.35:9848] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.42.53:2525] with esmtp (Farcaster) id 8db83032-f7c3-4c9e-a339-1f3a20149c11; Wed, 22 Jan 2025 10:21:15 +0000 (UTC) X-Farcaster-Flow-ID: 8db83032-f7c3-4c9e-a339-1f3a20149c11 Received: from EX19D009UWB001.ant.amazon.com (10.13.138.58) by EX19MTAUWB002.ant.amazon.com (10.250.64.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:01 +0000 Received: from EX19MTAUWB002.ant.amazon.com (10.250.64.231) by EX19D009UWB001.ant.amazon.com (10.13.138.58) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:00 +0000 Received: from email-imr-corp-prod-iad-all-1b-a03c1db8.us-east-1.amazon.com (10.25.36.214) by mail-relay.amazon.com (10.250.64.228) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39 via Frontend Transport; Wed, 22 Jan 2025 10:21:00 +0000 Received: from HFA15-G9FV5D3.amazon.com (unknown [10.85.143.175]) by email-imr-corp-prod-iad-all-1b-a03c1db8.us-east-1.amazon.com (Postfix) with ESMTP id 98C4080305; Wed, 22 Jan 2025 10:20:55 +0000 (UTC) From: David Arinzon To: David Miller , Jakub Kicinski , CC: David Arinzon , Eric Dumazet , Paolo Abeni , Richard Cochran , "Woodhouse, David" , "Machulsky, Zorik" , "Matushevsky, Alexander" , Saeed Bshara , "Wilson, Matt" , "Liguori, Anthony" , "Bshara, Nafea" , "Schmeilin, Evgeny" , "Belgazal, Netanel" , "Saidi, Ali" , "Herrenschmidt, Benjamin" , "Kiyanovski, Arthur" , "Dagan, Noam" , "Bernstein, Amit" , "Agroskin, Shay" , "Abboud, Osama" , "Ostrovsky, Evgeny" , "Tabachnik, Ofir" , "Machnikowski, Maciek" , "Rahul Rameshbabu" , Gal Pressman Subject: [PATCH v5 net-next 2/5] net: ena: PHC silent reset Date: Wed, 22 Jan 2025 12:20:37 +0200 Message-ID: <20250122102040.752-3-darinzon@amazon.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250122102040.752-1-darinzon@amazon.com> References: <20250122102040.752-1-darinzon@amazon.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org Each PHC device kernel registration receives a unique kernel index, which is associated with a new PHC device file located at "/dev/ptp". This device file serves as an interface for obtaining PHC timestamps. Examples of tools that use "/dev/ptp" include testptp [1] and chrony [2]. A reset flow may occur in the ENA driver while PHC is active. During a reset, the driver will unregister and then re-register the PHC device with the kernel. Under race conditions, particularly during heavy PHC loads, the driver’s reset flow might complete faster than the kernel’s PHC unregister/register process. This can result in the PHC index being different from what it was prior to the reset, as the PHC index is selected using kernel ID allocation [3]. While driver rmmod/insmod are done by the user, a reset may occur at anytime, without the user awareness, consequently, the driver might receive a new PHC index after the reset, potentially compromising the user experience. To prevent this issue, the PHC flow will detect the reset during PHC destruction and will skip the PHC unregister/register calls to preserve the kernel PHC index. During the reset flow, any attempt to get a PHC timestamp will fail as expected, but the kernel PHC index will remain unchanged. [1]: https://github.com/torvalds/linux/blob/v6.1/tools/testing/selftests/ptp/testptp.c [2]: https://github.com/mlichvar/chrony [3]: https://www.kernel.org/doc/html/latest/core-api/idr.html Signed-off-by: Amit Bernstein Signed-off-by: David Arinzon --- drivers/net/ethernet/amazon/ena/ena_phc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.c b/drivers/net/ethernet/amazon/ena/ena_phc.c index 87495de0..5c1acd88 100644 --- a/drivers/net/ethernet/amazon/ena/ena_phc.c +++ b/drivers/net/ethernet/amazon/ena/ena_phc.c @@ -107,6 +107,10 @@ static int ena_phc_register(struct ena_adapter *adapter) phc_info = adapter->phc_info; clock_info = &phc_info->clock_info; + /* PHC may already be registered in case of a reset */ + if (ena_phc_is_active(adapter)) + return 0; + phc_info->adapter = adapter; spin_lock_init(&phc_info->lock); @@ -133,7 +137,11 @@ static void ena_phc_unregister(struct ena_adapter *adapter) { struct ena_phc_info *phc_info = adapter->phc_info; - if (ena_phc_is_active(adapter)) { + /* During reset flow, PHC must stay registered + * to keep kernel's PHC index + */ + if (ena_phc_is_active(adapter) && + !test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) { ptp_clock_unregister(phc_info->clock); phc_info->clock = NULL; } From patchwork Wed Jan 22 10:20:38 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Arinzon, David" X-Patchwork-Id: 13947121 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp-fw-80008.amazon.com (smtp-fw-80008.amazon.com [99.78.197.219]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 088F3145FE0 for ; Wed, 22 Jan 2025 10:21:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=99.78.197.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541278; cv=none; b=PeSqA4FduQzirFFyvpDJQbjG+RrNY853MizYsHY0q/F+Zh3Nf3Zks9l42P4Ux2owC78R4MYf9Oeiqqw1xW1d1NtGTOuTNA+gBkfqeuxTy00FkfD4hvJliuslnjobfJLCm/gZ5C32JFqVv+hbx0anlfZEUvOP5gC2tdLZiYyKriM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541278; c=relaxed/simple; bh=IWRDNEJGtorkKJClEVpqVKqfdWoRUU6d9OpeaNaJZk4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=dNR9+jtWV1Dted6oxwjmHuMgX9iUq3BL4VsK88BZF/6zUiyV8PLc7mqd7JI+pIPw90BgZs20viMWg3DxGtiFninAeavATMRxW4mXep69k1hRAv400pv9X610OnSxbPeuOgwHuPc5+yTS0Lt6bY+xKbJK2cw97Fd28JlJg5AGc4Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b=EpS9WekJ; arc=none smtp.client-ip=99.78.197.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="EpS9WekJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1737541277; x=1769077277; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Sk6p9PgliEub32hg6O+islq6mXCm3h6z8IujnE4zmCc=; b=EpS9WekJLKQj/i/mMsGaXSns0V3Q7nAP02v1CAPqxl9nSjBSiAqL7AHj tfRCvGiHNqgwCG5XKIdNkqwczRGg98NEOJ5aB4E72o2uHyWJZmcTCnN7V iLr7yHZATiMcA1zjvqf3KiqG4YliqdllXyNm8WrnsBxMe2qahl3GkYjrR M=; X-IronPort-AV: E=Sophos;i="6.13,224,1732579200"; d="scan'208";a="163305952" Received: from pdx4-co-svc-p1-lb2-vlan3.amazon.com (HELO smtpout.prod.us-west-2.prod.farcaster.email.amazon.dev) ([10.25.36.214]) by smtp-border-fw-80008.pdx80.corp.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2025 10:21:13 +0000 Received: from EX19MTAUWA001.ant.amazon.com [10.0.7.35:64448] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.59.12:2525] with esmtp (Farcaster) id eaa0f16e-0c4b-4484-b24c-6f4624a1bba7; Wed, 22 Jan 2025 10:21:12 +0000 (UTC) X-Farcaster-Flow-ID: eaa0f16e-0c4b-4484-b24c-6f4624a1bba7 Received: from EX19D009UWB002.ant.amazon.com (10.13.138.74) by EX19MTAUWA001.ant.amazon.com (10.250.64.204) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:07 +0000 Received: from EX19MTAUWB002.ant.amazon.com (10.250.64.231) by EX19D009UWB002.ant.amazon.com (10.13.138.74) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:06 +0000 Received: from email-imr-corp-prod-iad-all-1b-a03c1db8.us-east-1.amazon.com (10.25.36.214) by mail-relay.amazon.com (10.250.64.228) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39 via Frontend Transport; Wed, 22 Jan 2025 10:21:06 +0000 Received: from HFA15-G9FV5D3.amazon.com (unknown [10.85.143.175]) by email-imr-corp-prod-iad-all-1b-a03c1db8.us-east-1.amazon.com (Postfix) with ESMTP id 5A0F380305; Wed, 22 Jan 2025 10:21:01 +0000 (UTC) From: David Arinzon To: David Miller , Jakub Kicinski , CC: David Arinzon , Eric Dumazet , Paolo Abeni , Richard Cochran , "Woodhouse, David" , "Machulsky, Zorik" , "Matushevsky, Alexander" , Saeed Bshara , "Wilson, Matt" , "Liguori, Anthony" , "Bshara, Nafea" , "Schmeilin, Evgeny" , "Belgazal, Netanel" , "Saidi, Ali" , "Herrenschmidt, Benjamin" , "Kiyanovski, Arthur" , "Dagan, Noam" , "Bernstein, Amit" , "Agroskin, Shay" , "Abboud, Osama" , "Ostrovsky, Evgeny" , "Tabachnik, Ofir" , "Machnikowski, Maciek" , "Rahul Rameshbabu" , Gal Pressman Subject: [PATCH v5 net-next 3/5] net: ena: Add PHC documentation Date: Wed, 22 Jan 2025 12:20:38 +0200 Message-ID: <20250122102040.752-4-darinzon@amazon.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250122102040.752-1-darinzon@amazon.com> References: <20250122102040.752-1-darinzon@amazon.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org Provide the relevant information and guidelines about the feature support in the ENA driver. Signed-off-by: Amit Bernstein Signed-off-by: David Arinzon --- .../device_drivers/ethernet/amazon/ena.rst | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst index 4561e8ab..12b13da0 100644 --- a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst +++ b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst @@ -56,6 +56,7 @@ ena_netdev.[ch] Main Linux kernel driver. ena_ethtool.c ethtool callbacks. ena_xdp.[ch] XDP files ena_pci_id_tbl.h Supported device IDs. +ena_phc.[ch] PTP hardware clock infrastructure (see `PHC`_ for more info) ================= ====================================================== Management Interface: @@ -221,6 +222,83 @@ descriptor it was received on would be recycled. When a packet smaller than RX copybreak bytes is received, it is copied into a new memory buffer and the RX descriptor is returned to HW. +.. _`PHC`: + +PTP Hardware Clock (PHC) +======================== +.. _`ptp-userspace-api`: https://docs.kernel.org/driver-api/ptp.html#ptp-hardware-clock-user-space-api +.. _`testptp`: https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/ptp/testptp.c + +ENA Linux driver supports PTP hardware clock providing timestamp reference to achieve nanosecond resolution. + +**PHC support** + +PHC depends on the PTP module, which needs to be either loaded as a module or compiled into the kernel. + +Verify if the PTP module is present: + +.. code-block:: shell + + grep -w '^CONFIG_PTP_1588_CLOCK=[ym]' /boot/config-`uname -r` + +- If no output is provided, the ENA driver cannot be loaded with PHC support. + +- ``CONFIG_PTP_1588_CLOCK=y``: the PTP module is already compiled and loaded inside the kernel binary file. + +- ``CONFIG_PTP_1588_CLOCK=m``: the PTP module needs to be loaded prior to loading the ENA driver: + +Load PTP module: + +.. code-block:: shell + + sudo modprobe ptp + +All available PTP clock sources can be tracked here: + +.. code-block:: shell + + ls /sys/class/ptp + +PHC support and capabilities can be verified using ethtool: + +.. code-block:: shell + + ethtool -T + +**PHC timestamp** + +To retrieve PHC timestamp, use `ptp-userspace-api`_, usage example using `testptp`_: + +.. code-block:: shell + + testptp -d /dev/ptp$(ethtool -T | awk '/PTP Hardware Clock:/ {print $NF}') -k 1 + +PHC get time requests should be within reasonable bounds, +avoid excessive utilization to ensure optimal performance and efficiency. +The ENA device restricts the frequency of PHC get time requests to a maximum +of 125 requests per second. If this limit is surpassed, the get time request +will fail, leading to an increment in the phc_err statistic. + +**PHC statistics** + +PHC can be monitored using :code:`ethtool -S` counters: + +================= ====================================================== +**phc_cnt** Number of successful retrieved timestamps (below expire timeout). +**phc_exp** Number of expired retrieved timestamps (above expire timeout). +**phc_skp** Number of skipped get time attempts (during block period). +**phc_err** Number of failed get time attempts (entering into block state). +================= ====================================================== + +PHC timeouts: + +================= ====================================================== +**expire** Max time for a valid timestamp retrieval, passing this threshold will fail + the get time request and block new requests until block timeout. +**block** Blocking period starts once get time request expires or fails, all get time + requests during block period will be skipped. +================= ====================================================== + Statistics ========== From patchwork Wed Jan 22 10:20:39 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Arinzon, David" X-Patchwork-Id: 13947124 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp-fw-6002.amazon.com (smtp-fw-6002.amazon.com [52.95.49.90]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8E61B20F970 for ; Wed, 22 Jan 2025 10:21:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=52.95.49.90 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541287; cv=none; b=JUpnfMuFLg1G92AfHTVMRZcekeBGcTZioA4ryhE27NTR7o6kqJALWy1VLeMeVKwRhaDHuqt9Nu4SUOMBNQY6/5KnRzo4apUUn+Pf9c7z3y9JXfjbJBMxzAtV51A9aoZ2UlZHhmfOAFii+d9UuQdy47IhX6ZE1F4YBdB6VvexVlg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541287; c=relaxed/simple; bh=ghm5N8r/3NFY3VhcvBSd9wCKwdbaoxidYfYf+OuLK0w=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sXS5SW2j13M3bJHMVg3IzdJff5d/fY/Lw4i7N1W9uKiphXLGGF6xa+m86ZUBV1YXFDmYjsdjooUgXZyVqzp/wi3SVl0prJMHVdYbURcUzsP9ghit/orOAG9wUUquC1WFzo5nGsd7yT9BovKBTbyRKnN9WGofyKwHBgMPGNFCzuM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b=DHDb2RDr; arc=none smtp.client-ip=52.95.49.90 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="DHDb2RDr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1737541285; x=1769077285; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mJKqF5mOvHlnd2aM86X0/KYqMuPdq09hyHDBIDf8KWU=; b=DHDb2RDrs/q+gLT51B4qxgDu7Dcf1YQf+eRvJ3oVF+xiPsn4LPVG18FD FId7VIriog9ufwOYZ3rjh7qpZYlrLO6ip4vP4do0t54jhFjRYy4nlBFWF 9nP7JtdUZquzax0Fd9v/f6SbFciMDGJPGqljWIn4QguQYKORjPB6pfkSW o=; X-IronPort-AV: E=Sophos;i="6.13,224,1732579200"; d="scan'208";a="465934554" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO smtpout.prod.us-east-1.prod.farcaster.email.amazon.dev) ([10.43.8.6]) by smtp-border-fw-6002.iad6.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2025 10:21:22 +0000 Received: from EX19MTAUEC001.ant.amazon.com [10.0.29.78:17429] by smtpin.naws.us-east-1.prod.farcaster.email.amazon.dev [10.0.91.109:2525] with esmtp (Farcaster) id c81696e0-4133-4432-9eed-004b16d1fa9e; Wed, 22 Jan 2025 10:21:22 +0000 (UTC) X-Farcaster-Flow-ID: c81696e0-4133-4432-9eed-004b16d1fa9e Received: from EX19D008UEA002.ant.amazon.com (10.252.134.125) by EX19MTAUEC001.ant.amazon.com (10.252.135.222) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:14 +0000 Received: from EX19MTAUEA001.ant.amazon.com (10.252.134.203) by EX19D008UEA002.ant.amazon.com (10.252.134.125) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:14 +0000 Received: from email-imr-corp-prod-pdx-all-2c-619df93b.us-west-2.amazon.com (10.43.8.2) by mail-relay.amazon.com (10.252.134.102) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39 via Frontend Transport; Wed, 22 Jan 2025 10:21:14 +0000 Received: from HFA15-G9FV5D3.amazon.com (unknown [10.85.143.175]) by email-imr-corp-prod-pdx-all-2c-619df93b.us-west-2.amazon.com (Postfix) with ESMTP id DB6B9404A2; Wed, 22 Jan 2025 10:21:07 +0000 (UTC) From: David Arinzon To: David Miller , Jakub Kicinski , CC: David Arinzon , Eric Dumazet , Paolo Abeni , Richard Cochran , "Woodhouse, David" , "Machulsky, Zorik" , "Matushevsky, Alexander" , Saeed Bshara , "Wilson, Matt" , "Liguori, Anthony" , "Bshara, Nafea" , "Schmeilin, Evgeny" , "Belgazal, Netanel" , "Saidi, Ali" , "Herrenschmidt, Benjamin" , "Kiyanovski, Arthur" , "Dagan, Noam" , "Bernstein, Amit" , "Agroskin, Shay" , "Abboud, Osama" , "Ostrovsky, Evgeny" , "Tabachnik, Ofir" , "Machnikowski, Maciek" , "Rahul Rameshbabu" , Gal Pressman Subject: [PATCH v5 net-next 4/5] net: ena: PHC error bound/flags support Date: Wed, 22 Jan 2025 12:20:39 +0200 Message-ID: <20250122102040.752-5-darinzon@amazon.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250122102040.752-1-darinzon@amazon.com> References: <20250122102040.752-1-darinzon@amazon.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org PHC algorithm is updated to support reading new PHC values. Until this change, the driver retrieved PHC timestamp from the device's PHC address, this change expands this API by adding 2 new values to ena_admin_phc_resp: 1. PHC error bound: PTP HW clock error bound refers to the maximum allowable difference between the clock of the device and the reference clock. The error bound is used to ensure that the clock of the device remains within a certain level of accuracy relative to the reference clock. The error bound (expressed in nanoseconds) is calculated by the device, taking into account the accuracy of the PTA device, march hare network, TOR, Chrony, Pacemaker and ENA driver read delay. Error bound (u32) may contain values of 0-4294967295 (nsec) while driver may only report values of 0-4294967294 (nsec) because max error bound value (4294967295) will be used to represent error bound read error. The error bound value is retrieved from the device by the driver upon every get PHC timestamp request and is cached for future retrieval by the user. 2. PHC error flags: Indicates any PHC timestamp and error bound errors. The error flags value is retrieved from the device by the driver upon every get PHC timestamp request. Any PHC error type will: 1. Enter the PHC into blocked state until passing blocking time 2. Return device busy error to timestamp caller 3. Return device busy error to error bound caller Signed-off-by: Amit Bernstein Signed-off-by: David Arinzon --- .../device_drivers/ethernet/amazon/ena.rst | 15 +++- .../net/ethernet/amazon/ena/ena_admin_defs.h | 28 +++++-- drivers/net/ethernet/amazon/ena/ena_com.c | 83 +++++++++++++------ drivers/net/ethernet/amazon/ena/ena_com.h | 16 +++- drivers/net/ethernet/amazon/ena/ena_phc.c | 3 +- 5 files changed, 107 insertions(+), 38 deletions(-) diff --git a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst index 12b13da0..19697f63 100644 --- a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst +++ b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst @@ -279,6 +279,16 @@ The ENA device restricts the frequency of PHC get time requests to a maximum of 125 requests per second. If this limit is surpassed, the get time request will fail, leading to an increment in the phc_err statistic. +**PHC error bound** + +PTP HW clock error bound refers to the maximum allowable difference +between the clock of the device and the reference clock. +The error bound is used to ensure that the clock of the device +remains within a certain level of accuracy relative to the reference +clock. The error bound (expressed in nanoseconds) is calculated by +the device and is retrieved and cached by the driver upon every get PHC +timestamp request. + **PHC statistics** PHC can be monitored using :code:`ethtool -S` counters: @@ -287,7 +297,10 @@ PHC can be monitored using :code:`ethtool -S` counters: **phc_cnt** Number of successful retrieved timestamps (below expire timeout). **phc_exp** Number of expired retrieved timestamps (above expire timeout). **phc_skp** Number of skipped get time attempts (during block period). -**phc_err** Number of failed get time attempts (entering into block state). +**phc_err** Number of failed get time attempts due to timestamp/error bound errors + (entering into block state). + Must remain below 1% of all PHC requests to maintain the desired level of + accuracy and reliability. ================= ====================================================== PHC timeouts: diff --git a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h index 28770e60..de5c28f5 100644 --- a/drivers/net/ethernet/amazon/ena/ena_admin_defs.h +++ b/drivers/net/ethernet/amazon/ena/ena_admin_defs.h @@ -128,8 +128,14 @@ enum ena_admin_get_stats_scope { ENA_ADMIN_ETH_TRAFFIC = 1, }; -enum ena_admin_phc_type { - ENA_ADMIN_PHC_TYPE_READLESS = 0, +enum ena_admin_phc_feature_version { + /* Readless with error_bound */ + ENA_ADMIN_PHC_FEATURE_VERSION_0 = 0, +}; + +enum ena_admin_phc_error_flags { + ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP = BIT(0), + ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND = BIT(1), }; /* ENA SRD configuration for ENI */ @@ -1031,10 +1037,10 @@ struct ena_admin_queue_ext_feature_desc { }; struct ena_admin_feature_phc_desc { - /* PHC type as defined in enum ena_admin_get_phc_type, - * used only for GET command. + /* PHC version as defined in enum ena_admin_phc_feature_version, + * used only for GET command as max supported PHC version by the device. */ - u8 type; + u8 version; /* Reserved - MBZ */ u8 reserved1[3]; @@ -1212,13 +1218,23 @@ struct ena_admin_ena_mmio_req_read_less_resp { }; struct ena_admin_phc_resp { + /* Request Id, received from DB register */ u16 req_id; u8 reserved1[6]; + /* PHC timestamp (nsec) */ u64 timestamp; - u8 reserved2[48]; + u8 reserved2[8]; + + /* Timestamp error limit (nsec) */ + u32 error_bound; + + /* Bit field of enum ena_admin_phc_error_flags */ + u32 error_flags; + + u8 reserved3[32]; }; /* aq_common_desc */ diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index c6b9939e..66b1ab92 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -44,8 +44,10 @@ /* PHC definitions */ #define ENA_PHC_DEFAULT_EXPIRE_TIMEOUT_USEC 10 #define ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC 1000 -#define ENA_PHC_TIMESTAMP_ERROR 0xFFFFFFFFFFFFFFFF +#define ENA_PHC_MAX_ERROR_BOUND 0xFFFFFFFF #define ENA_PHC_REQ_ID_OFFSET 0xDEAD +#define ENA_PHC_ERROR_FLAGS (ENA_ADMIN_PHC_ERROR_FLAG_TIMESTAMP | \ + ENA_ADMIN_PHC_ERROR_FLAG_ERROR_BOUND) /*****************************************************************************/ /*****************************************************************************/ @@ -1682,11 +1684,11 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev) struct ena_admin_set_feat_cmd set_feat_cmd; int ret = 0; - /* Get device PHC default configuration */ + /* Get default device PHC configuration */ ret = ena_com_get_feature(ena_dev, &get_feat_resp, ENA_ADMIN_PHC_CONFIG, - 0); + ENA_ADMIN_PHC_FEATURE_VERSION_0); if (unlikely(ret)) { netdev_err(ena_dev->net_device, "Failed to get PHC feature configuration, error: %d\n", @@ -1694,10 +1696,10 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev) return ret; } - /* Supporting only readless PHC retrieval */ - if (get_feat_resp.u.phc.type != ENA_ADMIN_PHC_TYPE_READLESS) { - netdev_err(ena_dev->net_device, "Unsupported PHC type, error: %d\n", - -EOPNOTSUPP); + /* Supporting only PHC V0 (readless mode with error bound) */ + if (get_feat_resp.u.phc.version != ENA_ADMIN_PHC_FEATURE_VERSION_0) { + netdev_err(ena_dev->net_device, "Unsupported PHC version (0x%X), error: %d\n", + get_feat_resp.u.phc.version, -EOPNOTSUPP); return -EOPNOTSUPP; } @@ -1720,7 +1722,7 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev) get_feat_resp.u.phc.block_timeout_usec : ENA_PHC_DEFAULT_BLOCK_TIMEOUT_USEC; - /* Sanity check - expire timeout must not be above skip timeout */ + /* Sanity check - expire timeout must not exceed block timeout */ if (phc->expire_timeout_usec > phc->block_timeout_usec) phc->expire_timeout_usec = phc->block_timeout_usec; @@ -1778,7 +1780,7 @@ void ena_com_phc_destroy(struct ena_com_dev *ena_dev) phc->virt_addr = NULL; } -int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) +int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp) { volatile struct ena_admin_phc_resp *read_resp = ena_dev->phc.virt_addr; const ktime_t zero_system_time = ktime_set(0, 0); @@ -1806,14 +1808,13 @@ int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) goto skip; } - /* PHC is in active state, update statistics according to - * req_id and timestamp + /* PHC is in active state, update statistics according + * to req_id and error_flags */ if ((READ_ONCE(read_resp->req_id) != phc->req_id) || - read_resp->timestamp == ENA_PHC_TIMESTAMP_ERROR) - /* Device didn't update req_id during blocking time - * or timestamp is invalid, this indicates on a - * device error + (read_resp->error_flags & ENA_PHC_ERROR_FLAGS)) + /* Device didn't update req_id during blocking time or + * timestamp is invalid, this indicates on a device error */ phc->stats.phc_err++; else @@ -1845,36 +1846,46 @@ int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp) while (1) { if (unlikely(ktime_after(ktime_get(), expire_time))) { /* Gave up waiting for updated req_id, - * PHC enters into blocked state until passing - * blocking time + * PHC enters into blocked state until passing blocking time, + * during this time any get PHC timestamp or error bound + * requests will fail with device busy error */ + phc->error_bound = ENA_PHC_MAX_ERROR_BOUND; ret = -EBUSY; break; } /* Check if req_id was updated by the device */ if (READ_ONCE(read_resp->req_id) != phc->req_id) { - /* req_id was not updated by the device, + /* req_id was not updated by the device yet, * check again on next loop */ continue; } - /* req_id was updated which indicates that PHC timestamp - * was updated too + /* req_id was updated by the device which indicates that + * PHC timestamp, error_bound and error_flags are updated too, + * checking errors before retrieving timestamp and + * error_bound values */ - *timestamp = read_resp->timestamp; - - /* PHC timestamp validty check */ - if (unlikely(*timestamp == ENA_PHC_TIMESTAMP_ERROR)) { - /* Retrieved invalid PHC timestamp, PHC enters into - * blocked state until passing blocking time + if (unlikely(read_resp->error_flags & ENA_PHC_ERROR_FLAGS)) { + /* Retrieved timestamp or error bound errors, + * PHC enters into blocked state until passing blocking time, + * during this time any get PHC timestamp or error bound + * requests will fail with device busy error */ + phc->error_bound = ENA_PHC_MAX_ERROR_BOUND; ret = -EBUSY; break; } - /* Retrieved valid PHC timestamp */ + /* PHC timestamp value is returned to the caller */ + *timestamp = read_resp->timestamp; + + /* Error bound value is cached for future retrieval by caller */ + phc->error_bound = read_resp->error_bound; + + /* Update statistic on valid PHC timestamp retrieval */ phc->stats.phc_cnt++; /* This indicates PHC state is active */ @@ -1888,6 +1899,24 @@ skip: return ret; } +int ena_com_phc_get_error_bound(struct ena_com_dev *ena_dev, u32 *error_bound) +{ + struct ena_com_phc_info *phc = &ena_dev->phc; + u32 local_error_bound = phc->error_bound; + + if (!phc->active) { + netdev_err(ena_dev->net_device, "PHC feature is not active in the device\n"); + return -EOPNOTSUPP; + } + + if (local_error_bound == ENA_PHC_MAX_ERROR_BOUND) + return -EBUSY; + + *error_bound = local_error_bound; + + return 0; +} + int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev) { struct ena_com_mmio_read *mmio_read = &ena_dev->mmio_read; diff --git a/drivers/net/ethernet/amazon/ena/ena_com.h b/drivers/net/ethernet/amazon/ena/ena_com.h index 3905d348..8df63eef 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.h +++ b/drivers/net/ethernet/amazon/ena/ena_com.h @@ -299,6 +299,9 @@ struct ena_com_phc_info { /* PHC shared memory - physical address */ dma_addr_t phys_addr; + /* Cached error bound per timestamp sample */ + u32 error_bound; + /* Request id sent to the device */ u16 req_id; @@ -458,12 +461,19 @@ int ena_com_phc_config(struct ena_com_dev *ena_dev); */ void ena_com_phc_destroy(struct ena_com_dev *ena_dev); -/* ena_com_phc_get - Retrieve PHC timestamp +/* ena_com_phc_get_timestamp - Retrieve PHC timestamp + * @ena_dev: ENA communication layer struct + * @timestamp: Retrieved PHC timestamp + * @return - 0 on success, negative value on failure + */ +int ena_com_phc_get_timestamp(struct ena_com_dev *ena_dev, u64 *timestamp); + +/* ena_com_phc_get_error_bound - Retrieve cached PHC error bound * @ena_dev: ENA communication layer struct - * @timestamp: Retrieve PHC timestamp + * @error_bound: Cached PHC error bound * @return - 0 on success, negative value on failure */ -int ena_com_phc_get(struct ena_com_dev *ena_dev, u64 *timestamp); +int ena_com_phc_get_error_bound(struct ena_com_dev *ena_dev, u32 *error_bound); /* ena_com_set_mmio_read_mode - Enable/disable the indirect mmio reg read mechanism * @ena_dev: ENA communication layer struct diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.c b/drivers/net/ethernet/amazon/ena/ena_phc.c index 5c1acd88..5ce9a32d 100644 --- a/drivers/net/ethernet/amazon/ena/ena_phc.c +++ b/drivers/net/ethernet/amazon/ena/ena_phc.c @@ -38,7 +38,8 @@ static int ena_phc_gettimex64(struct ptp_clock_info *clock_info, ptp_read_system_prets(sts); - rc = ena_com_phc_get(phc_info->adapter->ena_dev, ×tamp_nsec); + rc = ena_com_phc_get_timestamp(phc_info->adapter->ena_dev, + ×tamp_nsec); ptp_read_system_postts(sts); From patchwork Wed Jan 22 10:20:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Arinzon, David" X-Patchwork-Id: 13947123 X-Patchwork-Delegate: kuba@kernel.org Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.190.10]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 20595145FE0 for ; Wed, 22 Jan 2025 10:21:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=207.171.190.10 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541286; cv=none; b=Q/ARmjIYO9h3lzgViA2f8dyeFZtdpCh/+ni4Y6lpuh2dO11BfHfjCzP19QeyVGDVSungl30JyazH3TJMi+6I7/VbywXvC0A4Utz5btPHsOlnv15PHcGSieUMhMJZaKa1JF0IpqQZOe7R3FLVgpgaWB7hvC6BgaSrZG0xdD1+VrU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1737541286; c=relaxed/simple; bh=7i8Y44+/p7fUVNFBG0d6z/Vi32ANUIC/X85mfALNkwM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=daFy0O7E1APFf5zN0psEmFXeXt2UK80xPi8uC9tWTSp4wo+aOB05Qogt6uI3UiV62lsVY3UUQD4VGxalrj4kokE5OR2emmmVe8vgLJiAx1569gg0u/jnOF5TyfQknRrqZSymgXTOrjEP4IhtsC6cO+vPbsvNPr3RB0uJ1ZGokoM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com; spf=pass smtp.mailfrom=amazon.com; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b=k4dkRnR/; arc=none smtp.client-ip=207.171.190.10 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=amazon.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=amazon.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=amazon.com header.i=@amazon.com header.b="k4dkRnR/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1737541285; x=1769077285; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=J39HgrX/TRin+rw+6O/83e8/yek9FDryizOPWSrDcwc=; b=k4dkRnR/wn9tr9rZbSnmcEizLhtIPjxvTwYfP3UhCq9/V5K4GPmD59IK nrop8jWtoBKyzO8xhX+IKoVoZ4uA5qbtWVbBnhY6dcKQTXKnpDTCIc5b8 qVbXhVGvsCZx+luymykHZ2iBWxllH4uf7OdzHCtekgZGwwifvIm87ToG3 c=; X-IronPort-AV: E=Sophos;i="6.13,224,1732579200"; d="scan'208";a="402617359" Received: from pdx4-co-svc-p1-lb2-vlan2.amazon.com (HELO smtpout.prod.us-west-2.prod.farcaster.email.amazon.dev) ([10.25.36.210]) by smtp-border-fw-33001.sea14.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jan 2025 10:21:24 +0000 Received: from EX19MTAUWB002.ant.amazon.com [10.0.7.35:55956] by smtpin.naws.us-west-2.prod.farcaster.email.amazon.dev [10.0.25.114:2525] with esmtp (Farcaster) id f7c8862f-68ad-4d5f-aea9-1fab6ba2f35a; Wed, 22 Jan 2025 10:21:23 +0000 (UTC) X-Farcaster-Flow-ID: f7c8862f-68ad-4d5f-aea9-1fab6ba2f35a Received: from EX19D009UWC001.ant.amazon.com (10.13.138.163) by EX19MTAUWB002.ant.amazon.com (10.250.64.231) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:23 +0000 Received: from EX19MTAUWB001.ant.amazon.com (10.250.64.248) by EX19D009UWC001.ant.amazon.com (10.13.138.163) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39; Wed, 22 Jan 2025 10:21:23 +0000 Received: from email-imr-corp-prod-pdx-all-2c-619df93b.us-west-2.amazon.com (10.25.36.214) by mail-relay.amazon.com (10.250.64.254) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA) id 15.2.1258.39 via Frontend Transport; Wed, 22 Jan 2025 10:21:23 +0000 Received: from HFA15-G9FV5D3.amazon.com (unknown [10.85.143.175]) by email-imr-corp-prod-pdx-all-2c-619df93b.us-west-2.amazon.com (Postfix) with ESMTP id 4FF72404A2; Wed, 22 Jan 2025 10:21:17 +0000 (UTC) From: David Arinzon To: David Miller , Jakub Kicinski , CC: David Arinzon , Eric Dumazet , Paolo Abeni , Richard Cochran , "Woodhouse, David" , "Machulsky, Zorik" , "Matushevsky, Alexander" , Saeed Bshara , "Wilson, Matt" , "Liguori, Anthony" , "Bshara, Nafea" , "Schmeilin, Evgeny" , "Belgazal, Netanel" , "Saidi, Ali" , "Herrenschmidt, Benjamin" , "Kiyanovski, Arthur" , "Dagan, Noam" , "Bernstein, Amit" , "Agroskin, Shay" , "Abboud, Osama" , "Ostrovsky, Evgeny" , "Tabachnik, Ofir" , "Machnikowski, Maciek" , "Rahul Rameshbabu" , Gal Pressman Subject: [PATCH v5 net-next 5/5] net: ena: PHC enable and error_bound through sysfs Date: Wed, 22 Jan 2025 12:20:40 +0200 Message-ID: <20250122102040.752-6-darinzon@amazon.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250122102040.752-1-darinzon@amazon.com> References: <20250122102040.752-1-darinzon@amazon.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org This patch allows controlling PHC feature enablement through sysfs. The feature is disabled by default, and customers can use the `phc_enable` sysfs entry in order to enable it. In addition, customers are able to access the `phc_error_bound` sysfs entry in order to get the current error bound value. Documentation is also updated. Signed-off-by: David Arinzon --- .../device_drivers/ethernet/amazon/ena.rst | 20 ++++ drivers/net/ethernet/amazon/ena/Makefile | 2 +- drivers/net/ethernet/amazon/ena/ena_netdev.c | 20 +++- drivers/net/ethernet/amazon/ena/ena_netdev.h | 2 + drivers/net/ethernet/amazon/ena/ena_phc.c | 8 ++ drivers/net/ethernet/amazon/ena/ena_phc.h | 1 + drivers/net/ethernet/amazon/ena/ena_sysfs.c | 110 ++++++++++++++++++ drivers/net/ethernet/amazon/ena/ena_sysfs.h | 28 +++++ 8 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 drivers/net/ethernet/amazon/ena/ena_sysfs.c create mode 100644 drivers/net/ethernet/amazon/ena/ena_sysfs.h diff --git a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst index 19697f63..3b2744a7 100644 --- a/Documentation/networking/device_drivers/ethernet/amazon/ena.rst +++ b/Documentation/networking/device_drivers/ethernet/amazon/ena.rst @@ -53,6 +53,7 @@ ena_eth_io_defs.h Definition of ENA data path interface. ena_common_defs.h Common definitions for ena_com layer. ena_regs_defs.h Definition of ENA PCI memory-mapped (MMIO) registers. ena_netdev.[ch] Main Linux kernel driver. +ena_sysfs.[ch] Sysfs files. ena_ethtool.c ethtool callbacks. ena_xdp.[ch] XDP files ena_pci_id_tbl.h Supported device IDs. @@ -253,6 +254,17 @@ Load PTP module: sudo modprobe ptp +**PHC activation** + +The feature is turned off by default, in order to turn the feature on, +please use the following: + +- sysfs (during runtime): + +.. code-block:: shell + + echo 1 > /sys/bus/pci/devices//phc_enable + All available PTP clock sources can be tracked here: .. code-block:: shell @@ -289,6 +301,14 @@ clock. The error bound (expressed in nanoseconds) is calculated by the device and is retrieved and cached by the driver upon every get PHC timestamp request. +To retrieve the cached PHC error bound value, use the following: + +sysfs: + +.. code-block:: shell + + cat /sys/bus/pci/devices//phc_error_bound + **PHC statistics** PHC can be monitored using :code:`ethtool -S` counters: diff --git a/drivers/net/ethernet/amazon/ena/Makefile b/drivers/net/ethernet/amazon/ena/Makefile index 8c874177..d950ade6 100644 --- a/drivers/net/ethernet/amazon/ena/Makefile +++ b/drivers/net/ethernet/amazon/ena/Makefile @@ -5,4 +5,4 @@ obj-$(CONFIG_ENA_ETHERNET) += ena.o -ena-y := ena_netdev.o ena_com.o ena_eth_com.o ena_ethtool.o ena_xdp.o ena_phc.o +ena-y := ena_netdev.o ena_com.o ena_eth_com.o ena_ethtool.o ena_xdp.o ena_phc.o ena_sysfs.o diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 13c9d93e..db1d9d44 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -20,6 +20,7 @@ #include "ena_netdev.h" #include "ena_pci_id_tbl.h" +#include "ena_sysfs.h" #include "ena_xdp.h" #include "ena_phc.h" @@ -44,8 +45,6 @@ MODULE_DEVICE_TABLE(pci, ena_pci_tbl); static int ena_rss_init_default(struct ena_adapter *adapter); static void check_for_admin_com_state(struct ena_adapter *adapter); -static int ena_destroy_device(struct ena_adapter *adapter, bool graceful); -static int ena_restore_device(struct ena_adapter *adapter); static void ena_tx_timeout(struct net_device *dev, unsigned int txqueue) { @@ -3270,7 +3269,7 @@ err_disable_msix: return rc; } -static int ena_destroy_device(struct ena_adapter *adapter, bool graceful) +int ena_destroy_device(struct ena_adapter *adapter, bool graceful) { struct net_device *netdev = adapter->netdev; struct ena_com_dev *ena_dev = adapter->ena_dev; @@ -3321,7 +3320,7 @@ static int ena_destroy_device(struct ena_adapter *adapter, bool graceful) return rc; } -static int ena_restore_device(struct ena_adapter *adapter) +int ena_restore_device(struct ena_adapter *adapter) { struct ena_com_dev_get_features_ctx get_feat_ctx; struct ena_com_dev *ena_dev = adapter->ena_dev; @@ -4056,10 +4055,17 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) "Failed to enable and set the admin interrupts\n"); goto err_worker_destroy; } + + rc = ena_sysfs_init(&adapter->pdev->dev); + if (rc) { + dev_err(&pdev->dev, "Cannot init sysfs\n"); + goto err_free_msix; + } + rc = ena_rss_init_default(adapter); if (rc && (rc != -EOPNOTSUPP)) { dev_err(&pdev->dev, "Cannot init RSS rc: %d\n", rc); - goto err_free_msix; + goto err_terminate_sysfs; } ena_config_debug_area(adapter); @@ -4104,6 +4110,8 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) err_rss: ena_com_delete_debug_area(ena_dev); ena_com_rss_destroy(ena_dev); +err_terminate_sysfs: + ena_sysfs_terminate(&pdev->dev); err_free_msix: ena_com_dev_reset(ena_dev, ENA_REGS_RESET_INIT_ERR); /* stop submitting admin commands on a device that was reset */ @@ -4156,6 +4164,8 @@ static void __ena_shutoff(struct pci_dev *pdev, bool shutdown) } #endif /* CONFIG_RFS_ACCEL */ + ena_sysfs_terminate(&adapter->pdev->dev); + /* Make sure timer and reset routine won't be called after * freeing device resources. */ diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 7867cd7f..e3c7ed9c 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -416,6 +416,8 @@ static inline void ena_reset_device(struct ena_adapter *adapter, set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); } +int ena_destroy_device(struct ena_adapter *adapter, bool graceful); +int ena_restore_device(struct ena_adapter *adapter); int handle_invalid_req_id(struct ena_ring *ring, u16 req_id, struct ena_tx_buffer *tx_info, bool is_xdp); diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.c b/drivers/net/ethernet/amazon/ena/ena_phc.c index 5ce9a32d..add51c8d 100644 --- a/drivers/net/ethernet/amazon/ena/ena_phc.c +++ b/drivers/net/ethernet/amazon/ena/ena_phc.c @@ -229,3 +229,11 @@ int ena_phc_get_index(struct ena_adapter *adapter) return -1; } + +int ena_phc_get_error_bound(struct ena_adapter *adapter, u32 *error_bound_nsec) +{ + if (!ena_phc_is_active(adapter)) + return -EOPNOTSUPP; + + return ena_com_phc_get_error_bound(adapter->ena_dev, error_bound_nsec); +} diff --git a/drivers/net/ethernet/amazon/ena/ena_phc.h b/drivers/net/ethernet/amazon/ena/ena_phc.h index 7364fe71..9c47af84 100644 --- a/drivers/net/ethernet/amazon/ena/ena_phc.h +++ b/drivers/net/ethernet/amazon/ena/ena_phc.h @@ -33,5 +33,6 @@ int ena_phc_init(struct ena_adapter *adapter); void ena_phc_destroy(struct ena_adapter *adapter); int ena_phc_alloc(struct ena_adapter *adapter); void ena_phc_free(struct ena_adapter *adapter); +int ena_phc_get_error_bound(struct ena_adapter *adapter, u32 *error_bound); #endif /* ENA_PHC_H */ diff --git a/drivers/net/ethernet/amazon/ena/ena_sysfs.c b/drivers/net/ethernet/amazon/ena/ena_sysfs.c new file mode 100644 index 00000000..dd604cc5 --- /dev/null +++ b/drivers/net/ethernet/amazon/ena/ena_sysfs.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#include +#include +#include +#include + +#include "ena_com.h" +#include "ena_netdev.h" +#include "ena_phc.h" +#include "ena_sysfs.h" + +static ssize_t ena_phc_enable_set(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t len) +{ + struct ena_adapter *adapter = dev_get_drvdata(dev); + unsigned long phc_enable_val; + int rc; + + if (!ena_com_phc_supported(adapter->ena_dev)) { + netif_info(adapter, drv, adapter->netdev, + "Device doesn't support PHC"); + return -EOPNOTSUPP; + } + + rc = kstrtoul(buf, 10, &phc_enable_val); + if (rc < 0) + return rc; + + if (phc_enable_val != 0 && phc_enable_val != 1) + return -EINVAL; + + rtnl_lock(); + + /* No change in state */ + if ((bool)phc_enable_val == ena_phc_is_enabled(adapter)) + goto out; + + ena_phc_enable(adapter, phc_enable_val); + + ena_destroy_device(adapter, false); + rc = ena_restore_device(adapter); + +out: + rtnl_unlock(); + return rc ? rc : len; +} + +#define ENA_PHC_ENABLE_STR_MAX_LEN 3 + +static ssize_t ena_phc_enable_get(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct ena_adapter *adapter = dev_get_drvdata(dev); + + return snprintf(buf, ENA_PHC_ENABLE_STR_MAX_LEN, "%u\n", + ena_phc_is_enabled(adapter)); +} + +static DEVICE_ATTR(phc_enable, S_IRUGO | S_IWUSR, ena_phc_enable_get, + ena_phc_enable_set); + +/* Max PHC error bound string size takes into account max u32 value, + * null and new line characters. + */ +#define ENA_PHC_ERROR_BOUND_STR_MAX_LEN 12 + +static ssize_t ena_show_phc_error_bound(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ena_adapter *adapter = dev_get_drvdata(dev); + u32 error_bound_nsec = 0; + int rc; + + rc = ena_phc_get_error_bound(adapter, &error_bound_nsec); + if (rc != 0) + return rc; + + return snprintf(buf, ENA_PHC_ERROR_BOUND_STR_MAX_LEN, "%u\n", + error_bound_nsec); +} + +static DEVICE_ATTR(phc_error_bound, S_IRUGO, ena_show_phc_error_bound, NULL); + +/****************************************************************************** + *****************************************************************************/ +int ena_sysfs_init(struct device *dev) +{ + if (device_create_file(dev, &dev_attr_phc_enable)) + dev_err(dev, "Failed to create phc_enable sysfs entry"); + + if (device_create_file(dev, &dev_attr_phc_error_bound)) + dev_err(dev, "Failed to create phc_error_bound sysfs entry"); + + return 0; +} + +/****************************************************************************** + *****************************************************************************/ +void ena_sysfs_terminate(struct device *dev) +{ + device_remove_file(dev, &dev_attr_phc_enable); + device_remove_file(dev, &dev_attr_phc_error_bound); +} diff --git a/drivers/net/ethernet/amazon/ena/ena_sysfs.h b/drivers/net/ethernet/amazon/ena/ena_sysfs.h new file mode 100644 index 00000000..8c572eee --- /dev/null +++ b/drivers/net/ethernet/amazon/ena/ena_sysfs.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ +/* + * Copyright 2015-2020 Amazon.com, Inc. or its affiliates. All rights reserved. + */ + +#ifndef __ENA_SYSFS_H__ +#define __ENA_SYSFS_H__ + +#ifdef CONFIG_SYSFS + +int ena_sysfs_init(struct device *dev); + +void ena_sysfs_terminate(struct device *dev); + +#else /* CONFIG_SYSFS */ + +static inline int ena_sysfs_init(struct device *dev) +{ + return 0; +} + +static inline void ena_sysfs_terminate(struct device *dev) +{ +} + +#endif /* CONFIG_SYSFS */ + +#endif /* __ENA_SYSFS_H__ */