From patchwork Mon Sep 9 23:52:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 13797708 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 58AE0ECE58C for ; Mon, 9 Sep 2024 23:55:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=yHPzrmNPD3zzzc0VrtJQihZZBj2ZR2hmkkJkLH0acB0=; b=gkbyvAXJxY5goVHc42GA6uIWCq Q1e0FoeuyYboQbDXC94/DbryhHazoNMys4DZKHZDhsJVHRPDOaMX7oVlT4UlTuJ97Y1U/eItuGEaT i1EEVQcZBK7uXHPSmxZrkTMtZgyc8lzYS164xSz9QxROCvw0e/Ps9s7gRQ19MHBc10OekxBhxfCW4 5ZD0xiInFjkrKDqtZYOqmC7pt36v7Onzf+oZQN/pePCuP1HysytDXgaefnap1TijCmQP2NlC199QM KuFzGBOkFGIw8AN7+6wKCJKViP3NKHLR2FOLEPxT1ZZcHP+dYjn7mxfl/52Vo/JDMveu97SnQ5tKM rmJe8tXA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoE9-00000003d9c-0K8F; Mon, 09 Sep 2024 23:55:25 +0000 Received: from out-178.mta1.migadu.com ([2001:41d0:203:375::b2]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoB8-00000003cIM-48AK for linux-arm-kernel@lists.infradead.org; Mon, 09 Sep 2024 23:52:20 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1725925934; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yHPzrmNPD3zzzc0VrtJQihZZBj2ZR2hmkkJkLH0acB0=; b=DogIhdY0vx9kvLt8BQMT32QfDlE563f9V443Zs9s2MJk429lOiZ8uMm1uguM4xTxeOjXLz eeoVhQurKw6t3D8o/Dcq6rH1rzmULUbU1rH/546AooWto0hD0G0o2l4Yi/wsWnjOGGssHy Tmk0eR9gh5hoYuc+gR9u/bdzxr9Js+M= From: Sean Anderson To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Radhey Shyam Pandey , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Michal Simek , linux-kernel@vger.kernel.org, Sean Anderson Subject: [RFC PATCH net-next v2 1/6] net: xilinx: axienet: Add some symbolic constants for IRQ delay timer Date: Mon, 9 Sep 2024 19:52:03 -0400 Message-Id: <20240909235208.1331065-2-sean.anderson@linux.dev> In-Reply-To: <20240909235208.1331065-1-sean.anderson@linux.dev> References: <20240909235208.1331065-1-sean.anderson@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240909_165219_252375_22461F2A X-CRM114-Status: GOOD ( 11.25 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Instead of using literals, add some symbolic constants for the IRQ delay timer calculation. Signed-off-by: Sean Anderson --- Changes in v2: - New drivers/net/ethernet/xilinx/xilinx_axienet.h | 3 +++ drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 7 ++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index d70cb62ecf29..5c0a21ef96a4 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -119,6 +119,9 @@ #define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */ #define XAXIDMA_IRQ_ALL_MASK 0x00007000 /* All interrupts */ +/* Constant to convert delay counts to microseconds */ +#define XAXIDMA_DELAY_SCALE (125ULL * USEC_PER_SEC) + /* Default TX/RX Threshold and delay timer values for SGDMA mode */ #define XAXIDMA_DFT_TX_THRESHOLD 24 #define XAXIDMA_DFT_TX_USEC 50 diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index b065979db196..cf67d455da48 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -238,11 +238,8 @@ static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) /* 1 Timeout Interval = 125 * (clock period of SG clock) */ result = DIV64_U64_ROUND_CLOSEST((u64)coalesce_usec * clk_rate, - (u64)125000000); - if (result > 255) - result = 255; - - return result; + XAXIDMA_DELAY_SCALE); + return min(result, FIELD_MAX(XAXIDMA_DELAY_MASK)); } /** From patchwork Mon Sep 9 23:52:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 13797707 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 016F2ECE58E for ; Mon, 9 Sep 2024 23:54:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=7z7hMAYUJc0zmXWBPqYacY7Rnkdds/x2g+X1a1EEKWc=; b=hEGQEoNdDbqFGXnUjLx3kZKQW4 1Bbd2TrnmwWK0c6XkzuTXYc3qjcyYm6A/QZb/A+af6oaa4JOMKjHLv2qrHn/j7Ide1gTnR2C1d/Aa 5wmWChFGkSd1It3SydwEFYLz6PF9GjUfS5JAYZKsTmoy+lBhX8FETSvfRFWEcMF3LmU9A4zLAR/JB RP1yrsm/V+au8SzbDShSEf26BXLBGnjV7sRF8sv71FZHt5Fwt/6+DkDp/iu9I39krVteumCAsbuhl Kii002v0Ltq9kqO38e8vavi7JXfLFZFdHAQFBeegSRRgeUxWpk6D0a0dcvOhVTfGbJUzkm1lWgD3N JLrbqORQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoD9-00000003cqm-1DaP; Mon, 09 Sep 2024 23:54:23 +0000 Received: from out-182.mta1.migadu.com ([95.215.58.182]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoB7-00000003cIu-3vZx for linux-arm-kernel@lists.infradead.org; Mon, 09 Sep 2024 23:52:19 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1725925936; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7z7hMAYUJc0zmXWBPqYacY7Rnkdds/x2g+X1a1EEKWc=; b=CiI3DgmGYdI0RENTl31Uzr20M86Njzhc7NENiJIVtidhc/mMgY3sHUQeTDW4HlUaDIuPAE 0snie915zpP5Ei+PefJLA6LJoYe/qNLua5igU/E37474z98amymu5XyfHORTFZL2D5xpBX CIN4Qvl9YMfOyScqpQjHtNvVypS9x3A= From: Sean Anderson To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Radhey Shyam Pandey , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Michal Simek , linux-kernel@vger.kernel.org, Sean Anderson Subject: [RFC PATCH net-next v2 2/6] net: xilinx: axienet: Report an error for bad coalesce settings Date: Mon, 9 Sep 2024 19:52:04 -0400 Message-Id: <20240909235208.1331065-3-sean.anderson@linux.dev> In-Reply-To: <20240909235208.1331065-1-sean.anderson@linux.dev> References: <20240909235208.1331065-1-sean.anderson@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240909_165218_144905_8AF0FA3E X-CRM114-Status: GOOD ( 11.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Instead of silently ignoring invalid/unsupported settings, report an error. Additionally, relax the check for non-zero usecs to apply only when it will be used (i.e. when frames != 1). Signed-off-by: Sean Anderson --- Changes in v2: - New .../net/ethernet/xilinx/xilinx_axienet_main.c | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index cf67d455da48..bc987f7ca1ea 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -2048,14 +2048,25 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, return -EBUSY; } - if (ecoalesce->rx_max_coalesced_frames) - lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; - if (ecoalesce->rx_coalesce_usecs) - lp->coalesce_usec_rx = ecoalesce->rx_coalesce_usecs; - if (ecoalesce->tx_max_coalesced_frames) - lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; - if (ecoalesce->tx_coalesce_usecs) - lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs; + if (!ecoalesce->rx_max_coalesced_frames || + !ecoalesce->tx_max_coalesced_frames) { + NL_SET_ERR_MSG(extack, "frames must be non-zero"); + return -EINVAL; + } + + if ((ecoalesce->rx_max_coalesced_frames > 1 && + !ecoalesce->rx_coalesce_usecs) || + (ecoalesce->tx_max_coalesced_frames > 1 && + !ecoalesce->tx_coalesce_usecs)) { + NL_SET_ERR_MSG(extack, + "usecs must be non-zero when frames is greater than one"); + return -EINVAL; + } + + lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; + lp->coalesce_usec_rx = ecoalesce->rx_coalesce_usecs; + lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; + lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs; return 0; } From patchwork Mon Sep 9 23:52:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 13797709 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BB4A6ECE58E for ; Mon, 9 Sep 2024 23:56:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=5ssZDLWuhmg7BjjNQ/xg73GUgeYAa7avYss6Mbv4fsg=; b=RLh4fQMTxgw9FSdAVmCz9/+ix+ Ee0DyFVTq7yp7tXJZYBzsjaP5nQGkAcTNbIwOkBsYKIUhkvA3X5WASeEl9+AAa0ExnIVY5w3rtmHo b+jN3lZZtVIlntkbTbXJh/CxdpCGlQmURl6fQVswc2H84kwnyUDQKe1hNnm9YjwKmv75C0QrVZR7B TVPSFpmc8jgSCrmwUVh129LO8/LkjTQQqqXZUpl3ugTQnYIMPnMpJiRg8tuc8LJz/5Mc8n2otKGhS T/WfmaUZerOmowGLIllzcouoo9pAvDEeWP4EHiGXa9pXO1t/FDbDHD27zCslmFAFW6D1JpW6IpsWp Yr1eb3Ag==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoF6-00000003dGN-2cVm; Mon, 09 Sep 2024 23:56:24 +0000 Received: from out-185.mta1.migadu.com ([2001:41d0:203:375::b9]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoBB-00000003cJl-0pce for linux-arm-kernel@lists.infradead.org; Mon, 09 Sep 2024 23:52:22 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1725925939; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5ssZDLWuhmg7BjjNQ/xg73GUgeYAa7avYss6Mbv4fsg=; b=JBV36mWH6/vKdO3LxZ67bLUKmC9zRy4wAS/wjmJOn7VbfPzPB0jNihXuwUq3PSjbq6j4rP RaNprjiFVc2ShMZ/CYLeqB4uWYukNY25z8AbfdfPDhVA6pjSkDHQ0AbB80tbxf8l9lyKJ4 TvpyafBSztvtwH58vfhQpoC/uAWMXqg= From: Sean Anderson To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Radhey Shyam Pandey , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Michal Simek , linux-kernel@vger.kernel.org, Sean Anderson Subject: [RFC PATCH net-next v2 3/6] net: xilinx: axienet: Combine CR calculation Date: Mon, 9 Sep 2024 19:52:05 -0400 Message-Id: <20240909235208.1331065-4-sean.anderson@linux.dev> In-Reply-To: <20240909235208.1331065-1-sean.anderson@linux.dev> References: <20240909235208.1331065-1-sean.anderson@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240909_165221_529940_6BE96707 X-CRM114-Status: GOOD ( 15.73 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Combine the common parts of the CR calculations for better code reuse. While we're at it, simplify the code a bit. Signed-off-by: Sean Anderson --- Changes in v2: - Split off from runtime coalesce modification support drivers/net/ethernet/xilinx/xilinx_axienet.h | 2 - .../net/ethernet/xilinx/xilinx_axienet_main.c | 69 ++++++++++--------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 5c0a21ef96a4..c43ce8f7590c 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -112,8 +112,6 @@ #define XAXIDMA_DELAY_MASK ((u32)0xFF000000) /* Delay timeout counter */ #define XAXIDMA_COALESCE_MASK ((u32)0x00FF0000) /* Coalesce counter */ -#define XAXIDMA_DELAY_SHIFT 24 - #define XAXIDMA_IRQ_IOC_MASK 0x00001000 /* Completion intr */ #define XAXIDMA_IRQ_DELAY_MASK 0x00002000 /* Delay interrupt */ #define XAXIDMA_IRQ_ERROR_MASK 0x00004000 /* Error interrupt */ diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index bc987f7ca1ea..bff94d378b9f 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -224,22 +224,41 @@ static void axienet_dma_bd_release(struct net_device *ndev) } /** - * axienet_usec_to_timer - Calculate IRQ delay timer value - * @lp: Pointer to the axienet_local structure - * @coalesce_usec: Microseconds to convert into timer value + * axienet_calc_cr() - Calculate control register value + * @lp: Device private data + * @coalesce_count: Number of completions before an interrupt + * @coalesce_usec: Microseconds after the last completion before an interrupt + * + * Calculate a control register value based on the coalescing settings. The + * run/stop bit is not set. */ -static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) +static u32 axienet_calc_cr(struct axienet_local *lp, u32 count, u32 usec) { - u32 result; - u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ + u32 cr; - if (lp->axi_clk) - clk_rate = clk_get_rate(lp->axi_clk); + count = min(count, FIELD_MAX(XAXIDMA_COALESCE_MASK)); + cr = FIELD_PREP(XAXIDMA_COALESCE_MASK, count) | XAXIDMA_IRQ_IOC_MASK | + XAXIDMA_IRQ_ERROR_MASK; + /* Only set interrupt delay timer if not generating an interrupt on + * the first packet. Otherwise leave at 0 to disable delay interrupt. + */ + if (count > 1) { + u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ + u32 timer; - /* 1 Timeout Interval = 125 * (clock period of SG clock) */ - result = DIV64_U64_ROUND_CLOSEST((u64)coalesce_usec * clk_rate, - XAXIDMA_DELAY_SCALE); - return min(result, FIELD_MAX(XAXIDMA_DELAY_MASK)); + if (lp->axi_clk) + clk_rate = clk_get_rate(lp->axi_clk); + + /* 1 Timeout Interval = 125 * (clock period of SG clock) */ + timer = DIV64_U64_ROUND_CLOSEST((u64)usec * clk_rate, + XAXIDMA_DELAY_SCALE); + + timer = min(timer, FIELD_MAX(XAXIDMA_DELAY_MASK)); + cr |= FIELD_PREP(XAXIDMA_DELAY_MASK, timer) | + XAXIDMA_IRQ_DELAY_MASK; + } + + return cr; } /** @@ -249,31 +268,13 @@ static u32 axienet_usec_to_timer(struct axienet_local *lp, u32 coalesce_usec) static void axienet_dma_start(struct axienet_local *lp) { /* Start updating the Rx channel control register */ - lp->rx_dma_cr = FIELD_PREP(XAXIDMA_COALESCE_MASK, - min(lp->coalesce_count_rx, - FIELD_MAX(XAXIDMA_COALESCE_MASK))) | - XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK; - /* Only set interrupt delay timer if not generating an interrupt on - * the first RX packet. Otherwise leave at 0 to disable delay interrupt. - */ - if (lp->coalesce_count_rx > 1) - lp->rx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_rx) - << XAXIDMA_DELAY_SHIFT) | - XAXIDMA_IRQ_DELAY_MASK; + lp->rx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_rx, + lp->coalesce_usec_rx); axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); /* Start updating the Tx channel control register */ - lp->tx_dma_cr = FIELD_PREP(XAXIDMA_COALESCE_MASK, - min(lp->coalesce_count_tx, - FIELD_MAX(XAXIDMA_COALESCE_MASK))) | - XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_ERROR_MASK; - /* Only set interrupt delay timer if not generating an interrupt on - * the first TX packet. Otherwise leave at 0 to disable delay interrupt. - */ - if (lp->coalesce_count_tx > 1) - lp->tx_dma_cr |= (axienet_usec_to_timer(lp, lp->coalesce_usec_tx) - << XAXIDMA_DELAY_SHIFT) | - XAXIDMA_IRQ_DELAY_MASK; + lp->tx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_tx, + lp->coalesce_usec_tx); axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); /* Populate the tail pointer and bring the Rx Axi DMA engine out of From patchwork Mon Sep 9 23:52:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 13797710 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 72A82ECE58C for ; Mon, 9 Sep 2024 23:57:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=X0exwUPvNKG4vKL/SWcmseZgDtvlCzMCkK2iDMIpCRM=; b=BMxcQjO0jl4eFKTzHWar7uPjM2 PpmzsAmijCVgMORXaS8AJfZaMxVXmru0jjzvOeX5L7aOaLoKpsn480ho8TYh+0+jaT2L5QmwjR/1N /gh+ejEVhcHIGklgCmKb+eJ8+8rrlRk7oGDlFCb8pc2Qyc8ih+0clKrat3u6GvJ5x2gN37Ew2ob6E Fc9ke4loV9Vfa+mDYkitdwENXP+fo0vKfsEA81pztUz1SRQX9JC5rfk2Os3R6Wh2V538+avP95UIg vbCzZ2vg3yDCtoAvaGdZrEo/mWbElhxJdeTwsts2KDzvor3FshyNzmqJs2qm31DD630JfvpkqIGBb ZC1/Wntg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoG4-00000003dQ6-44f0; Mon, 09 Sep 2024 23:57:24 +0000 Received: from out-184.mta1.migadu.com ([2001:41d0:203:375::b8]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoBC-00000003cK1-36I0 for linux-arm-kernel@lists.infradead.org; Mon, 09 Sep 2024 23:52:24 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1725925940; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=X0exwUPvNKG4vKL/SWcmseZgDtvlCzMCkK2iDMIpCRM=; b=G2yhRSpRDLQG6q3ROB7VxAh6yLqv5rEY5mk1TaiMx8/XVAr2NqoVuFH6wWjOwra0hgEJ71 nlwuRHvbOZHzNQN1CPd3ysWR+aJTZvCCxS1nhDrRHvWx3PUknHwMZS/uWRqT5pSivQOqcf 33TRJfX6vDsJkeEm9pouKkmEPX3g2eU= From: Sean Anderson To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Radhey Shyam Pandey , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Michal Simek , linux-kernel@vger.kernel.org, Sean Anderson Subject: [RFC PATCH net-next v2 4/6] net: xilinx: axienet: Support adjusting coalesce settings while running Date: Mon, 9 Sep 2024 19:52:06 -0400 Message-Id: <20240909235208.1331065-5-sean.anderson@linux.dev> In-Reply-To: <20240909235208.1331065-1-sean.anderson@linux.dev> References: <20240909235208.1331065-1-sean.anderson@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240909_165222_954459_5C7CD014 X-CRM114-Status: GOOD ( 26.46 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org In preparation for adaptive IRQ coalescing, we first need to support adjusting the settings at runtime. The existing code doesn't require any locking because - dma_start is the only function that modifies rx/tx_dma_cr. It is always called with IRQs and NAPI disabled, so nothing else is touching the hardware. - The IRQs don't race with poll, since the latter is a softirq. - The IRQs don't race with dma_stop since they both just clear the control registers. - dma_stop doesn't race with poll since the former is called with NAPI disabled. However, once we introduce another function that modifies rx/tx_dma_cr, we need to have some locking to prevent races. Introduce two locks to protect these variables and their registers. The control register values are now generated where the coalescing settings are set. Converting coalescing settings to control register values may require sleeping because of clk_get_rate. However, the read/modify/write of the control registers themselves can't sleep because it needs to happen in IRQ context. By pre-calculating the control register values, we avoid introducing an additional mutex. Since axienet_dma_start writes the control settings when it runs, we don't bother updating the CR registers when rx/tx_dma_started is false. This prevents any issues from writing to the control registers in the middle of a reset sequence. Signed-off-by: Sean Anderson --- Changes in v2: - Don't use spin_lock_irqsave when we know the context - Split the CR calculation refactor from runtime coalesce settings adjustment support for easier review. - Have axienet_update_coalesce_rx/tx take the cr value/mask instead of calculating it with axienet_calc_cr. This will make it easier to add partial updates in the next few commits. - Split off CR calculation merging into another patch drivers/net/ethernet/xilinx/xilinx_axienet.h | 8 ++ .../net/ethernet/xilinx/xilinx_axienet_main.c | 125 +++++++++++++++--- 2 files changed, 114 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index c43ce8f7590c..f0864cb8defe 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -484,7 +484,9 @@ struct skbuf_dma_descriptor { * @regs: Base address for the axienet_local device address space * @dma_regs: Base address for the axidma device address space * @napi_rx: NAPI RX control structure + * @rx_cr_lock: Lock protecting @rx_dma_cr, its register, and @rx_dma_started * @rx_dma_cr: Nominal content of RX DMA control register + * @rx_dma_started: Set when RX DMA is started * @rx_bd_v: Virtual address of the RX buffer descriptor ring * @rx_bd_p: Physical address(start address) of the RX buffer descr. ring * @rx_bd_num: Size of RX buffer descriptor ring @@ -494,7 +496,9 @@ struct skbuf_dma_descriptor { * @rx_bytes: RX byte count for statistics * @rx_stat_sync: Synchronization object for RX stats * @napi_tx: NAPI TX control structure + * @tx_cr_lock: Lock protecting @tx_dma_cr, its register, and @tx_dma_started * @tx_dma_cr: Nominal content of TX DMA control register + * @tx_dma_started: Set when TX DMA is started * @tx_bd_v: Virtual address of the TX buffer descriptor ring * @tx_bd_p: Physical address(start address) of the TX buffer descr. ring * @tx_bd_num: Size of TX buffer descriptor ring @@ -566,7 +570,9 @@ struct axienet_local { void __iomem *dma_regs; struct napi_struct napi_rx; + spinlock_t rx_cr_lock; u32 rx_dma_cr; + bool rx_dma_started; struct axidma_bd *rx_bd_v; dma_addr_t rx_bd_p; u32 rx_bd_num; @@ -576,7 +582,9 @@ struct axienet_local { struct u64_stats_sync rx_stat_sync; struct napi_struct napi_tx; + spinlock_t tx_cr_lock; u32 tx_dma_cr; + bool tx_dma_started; struct axidma_bd *tx_bd_v; dma_addr_t tx_bd_p; u32 tx_bd_num; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index bff94d378b9f..6bcb605aa67e 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -267,16 +267,12 @@ static u32 axienet_calc_cr(struct axienet_local *lp, u32 count, u32 usec) */ static void axienet_dma_start(struct axienet_local *lp) { + spin_lock_irq(&lp->rx_cr_lock); + /* Start updating the Rx channel control register */ - lp->rx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_rx, - lp->coalesce_usec_rx); + lp->rx_dma_cr &= ~XAXIDMA_CR_RUNSTOP_MASK; axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); - /* Start updating the Tx channel control register */ - lp->tx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_tx, - lp->coalesce_usec_tx); - axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); - /* Populate the tail pointer and bring the Rx Axi DMA engine out of * halted state. This will make the Rx side ready for reception. */ @@ -285,6 +281,14 @@ static void axienet_dma_start(struct axienet_local *lp) axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (lp->rx_bd_num - 1))); + lp->rx_dma_started = true; + + spin_unlock_irq(&lp->rx_cr_lock); + spin_lock_irq(&lp->tx_cr_lock); + + /* Start updating the Tx channel control register */ + lp->tx_dma_cr &= ~XAXIDMA_CR_RUNSTOP_MASK; + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); /* Write to the RS (Run-stop) bit in the Tx channel control register. * Tx channel is now ready to run. But only after we write to the @@ -293,6 +297,9 @@ static void axienet_dma_start(struct axienet_local *lp) axienet_dma_out_addr(lp, XAXIDMA_TX_CDESC_OFFSET, lp->tx_bd_p); lp->tx_dma_cr |= XAXIDMA_CR_RUNSTOP_MASK; axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); + lp->tx_dma_started = true; + + spin_unlock_irq(&lp->tx_cr_lock); } /** @@ -628,14 +635,22 @@ static void axienet_dma_stop(struct axienet_local *lp) int count; u32 cr, sr; - cr = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); - cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK); + spin_lock_irq(&lp->rx_cr_lock); + + cr = lp->rx_dma_cr & ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK); axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); + lp->rx_dma_started = false; + + spin_unlock_irq(&lp->rx_cr_lock); synchronize_irq(lp->rx_irq); - cr = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); - cr &= ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK); + spin_lock_irq(&lp->tx_cr_lock); + + cr = lp->tx_dma_cr & ~(XAXIDMA_CR_RUNSTOP_MASK | XAXIDMA_IRQ_ALL_MASK); axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); + lp->tx_dma_started = false; + + spin_unlock_irq(&lp->tx_cr_lock); synchronize_irq(lp->tx_irq); /* Give DMAs a chance to halt gracefully */ @@ -979,7 +994,9 @@ static int axienet_tx_poll(struct napi_struct *napi, int budget) * cause an immediate interrupt if any TX packets are * already pending. */ + spin_lock_irq(&lp->tx_cr_lock); axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, lp->tx_dma_cr); + spin_unlock_irq(&lp->tx_cr_lock); } return packets; } @@ -1245,7 +1262,9 @@ static int axienet_rx_poll(struct napi_struct *napi, int budget) * cause an immediate interrupt if any RX packets are * already pending. */ + spin_lock_irq(&lp->rx_cr_lock); axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, lp->rx_dma_cr); + spin_unlock_irq(&lp->rx_cr_lock); } return packets; } @@ -1283,13 +1302,16 @@ static irqreturn_t axienet_tx_irq(int irq, void *_ndev) /* Disable further TX completion interrupts and schedule * NAPI to handle the completions. */ - u32 cr = lp->tx_dma_cr; + u32 cr; + spin_lock(&lp->tx_cr_lock); + cr = lp->tx_dma_cr; cr &= ~(XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK); if (napi_schedule_prep(&lp->napi_tx)) { axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); __napi_schedule_irqoff(&lp->napi_tx); } + spin_unlock(&lp->tx_cr_lock); } return IRQ_HANDLED; @@ -1328,13 +1350,16 @@ static irqreturn_t axienet_rx_irq(int irq, void *_ndev) /* Disable further RX completion interrupts and schedule * NAPI receive. */ - u32 cr = lp->rx_dma_cr; + u32 cr; + spin_lock(&lp->rx_cr_lock); + cr = lp->rx_dma_cr; cr &= ~(XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK); if (napi_schedule_prep(&lp->napi_rx)) { axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); __napi_schedule_irqoff(&lp->napi_rx); } + spin_unlock(&lp->rx_cr_lock); } return IRQ_HANDLED; @@ -1994,6 +2019,62 @@ axienet_ethtools_set_pauseparam(struct net_device *ndev, return phylink_ethtool_set_pauseparam(lp->phylink, epauseparm); } +/** + * axienet_set_cr_rx() - Set RX CR + * @lp: Device private data + * @cr: Value to write to the RX CR + * @mask: Bits to set from @cr + */ +static void axienet_update_coalesce_rx(struct axienet_local *lp, u32 cr, + u32 mask) +{ + spin_lock_irq(&lp->rx_cr_lock); + lp->rx_dma_cr &= ~mask; + lp->rx_dma_cr |= cr; + /* If DMA isn't started, then the settings will be applied the next + * time dma_start() is called. + */ + if (lp->rx_dma_started) { + u32 reg = axienet_dma_in32(lp, XAXIDMA_RX_CR_OFFSET); + + /* Don't enable IRQs if they are disabled by NAPI */ + if (reg & XAXIDMA_IRQ_ALL_MASK) + cr = lp->rx_dma_cr; + else + cr = lp->rx_dma_cr & ~XAXIDMA_IRQ_ALL_MASK; + axienet_dma_out32(lp, XAXIDMA_RX_CR_OFFSET, cr); + } + spin_unlock_irq(&lp->rx_cr_lock); +} + +/** + * axienet_set_cr_tx() - Set TX CR + * @lp: Device private data + * @cr: Value to write to the TX CR + * @mask: Bits to set from @cr + */ +static void axienet_update_coalesce_tx(struct axienet_local *lp, u32 cr, + u32 mask) +{ + spin_lock_irq(&lp->tx_cr_lock); + lp->tx_dma_cr &= ~mask; + lp->tx_dma_cr |= cr; + /* If DMA isn't started, then the settings will be applied the next + * time dma_start() is called. + */ + if (lp->tx_dma_started) { + u32 reg = axienet_dma_in32(lp, XAXIDMA_TX_CR_OFFSET); + + /* Don't enable IRQs if they are disabled by NAPI */ + if (reg & XAXIDMA_IRQ_ALL_MASK) + cr = lp->tx_dma_cr; + else + cr = lp->tx_dma_cr & ~XAXIDMA_IRQ_ALL_MASK; + axienet_dma_out32(lp, XAXIDMA_TX_CR_OFFSET, cr); + } + spin_unlock_irq(&lp->tx_cr_lock); +} + /** * axienet_ethtools_get_coalesce - Get DMA interrupt coalescing count. * @ndev: Pointer to net_device structure @@ -2042,12 +2123,7 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, struct netlink_ext_ack *extack) { struct axienet_local *lp = netdev_priv(ndev); - - if (netif_running(ndev)) { - NL_SET_ERR_MSG(extack, - "Please stop netif before applying configuration"); - return -EBUSY; - } + u32 cr; if (!ecoalesce->rx_max_coalesced_frames || !ecoalesce->tx_max_coalesced_frames) { @@ -2069,6 +2145,11 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs; + cr = axienet_calc_cr(lp, lp->coalesce_count_rx, lp->coalesce_usec_rx); + axienet_update_coalesce_rx(lp, cr, ~XAXIDMA_CR_RUNSTOP_MASK); + + cr = axienet_calc_cr(lp, lp->coalesce_count_tx, lp->coalesce_usec_tx); + axienet_update_coalesce_tx(lp, cr, ~XAXIDMA_CR_RUNSTOP_MASK); return 0; } @@ -2853,10 +2934,16 @@ static int axienet_probe(struct platform_device *pdev) axienet_set_mac_address(ndev, NULL); } + spin_lock_init(&lp->rx_cr_lock); + spin_lock_init(&lp->tx_cr_lock); lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; lp->coalesce_usec_rx = XAXIDMA_DFT_RX_USEC; lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC; + lp->rx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_rx, + lp->coalesce_usec_rx); + lp->tx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_tx, + lp->coalesce_usec_tx); ret = axienet_mdio_setup(lp); if (ret) From patchwork Mon Sep 9 23:52:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 13797711 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 23360ECE58E for ; Mon, 9 Sep 2024 23:58:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=RJdpdx91YG1zNlUWl852ey9iK3iuCbq4oAOQKlh44hg=; b=FoQ+ZMdFHyuG3q8KwSwLZC243s uvigoJsaLtfpIZwjVWgS8WFvy9hlZ7V6F6r0tEao4LFBCkqccBGclTeBEmPwl5LGhp/mg2hwNvb4Z +TnHDxk09ozJNi4FcgcDnD7hbMJO58A9iItjDgj3DLugcOIEb1BWjP1xoYAmCNxxbGe9IoN+Iqm9u 0bamPoSyx0SAe2xZEWMZuuRMv/F332E8nayLjKz5z300GfYa4KjMVabU3wkv0qgp2vyKByI6g9p/V 4BGBvf2+uxhNWF5Fnz2U0nAmXMh0J80ozCjzQQKcezm/hZMHSmH4HC4uxzQCAkfhkMSwQ6Rg6rWUC VwauMtug==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoH4-00000003das-1PZ8; Mon, 09 Sep 2024 23:58:26 +0000 Received: from out-174.mta1.migadu.com ([95.215.58.174]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoBE-00000003cKU-31OU for linux-arm-kernel@lists.infradead.org; Mon, 09 Sep 2024 23:52:26 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1725925942; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RJdpdx91YG1zNlUWl852ey9iK3iuCbq4oAOQKlh44hg=; b=afkAHv+MeQvv+4DUqN76wtutiZ6PDOuK97AQ8aCDiVkc/d7ve9Li4YerTYmk2+s6rAZfVi OYSLrOAwkFJuzl5ou8sFrC6wkBGjMUTnuPtupcqp/lqE0yLNEvKgfsvfBgSjVl8zXh8Hcj W5vL2ipE0dpNz5KIIKZ8fZwtrlgNPDo= From: Sean Anderson To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Radhey Shyam Pandey , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Michal Simek , linux-kernel@vger.kernel.org, Sean Anderson Subject: [RFC PATCH net-next v2 5/6] net: xilinx: axienet: Get coalesce parameters from driver state Date: Mon, 9 Sep 2024 19:52:07 -0400 Message-Id: <20240909235208.1331065-6-sean.anderson@linux.dev> In-Reply-To: <20240909235208.1331065-1-sean.anderson@linux.dev> References: <20240909235208.1331065-1-sean.anderson@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240909_165224_933838_2AB75CB0 X-CRM114-Status: GOOD ( 16.19 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The cr variables now contain the same values as the control registers themselves. Extract/calculate the values from the variables instead of saving the user-specified values. This allows us to remove some bookeeping, and also lets the user know what the actual coalesce settings are. Signed-off-by: Sean Anderson --- Changes in v2: - New drivers/net/ethernet/xilinx/xilinx_axienet.h | 8 --- .../net/ethernet/xilinx/xilinx_axienet_main.c | 70 +++++++++++++------ 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index f0864cb8defe..33d05e55567e 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -533,10 +533,6 @@ struct skbuf_dma_descriptor { * @rxmem: Stores rx memory size for jumbo frame handling. * @csum_offload_on_tx_path: Stores the checksum selection on TX side. * @csum_offload_on_rx_path: Stores the checksum selection on RX side. - * @coalesce_count_rx: Store the irq coalesce on RX side. - * @coalesce_usec_rx: IRQ coalesce delay for RX - * @coalesce_count_tx: Store the irq coalesce on TX side. - * @coalesce_usec_tx: IRQ coalesce delay for TX * @use_dmaengine: flag to check dmaengine framework usage. * @tx_chan: TX DMA channel. * @rx_chan: RX DMA channel. @@ -617,10 +613,6 @@ struct axienet_local { int csum_offload_on_tx_path; int csum_offload_on_rx_path; - u32 coalesce_count_rx; - u32 coalesce_usec_rx; - u32 coalesce_count_tx; - u32 coalesce_usec_tx; u8 use_dmaengine; struct dma_chan *tx_chan; struct dma_chan *rx_chan; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 6bcb605aa67e..eb9600417d81 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -223,6 +223,13 @@ static void axienet_dma_bd_release(struct net_device *ndev) lp->rx_bd_p); } +static u64 axienet_dma_rate(struct axienet_local *lp) +{ + if (lp->axi_clk) + return clk_get_rate(lp->axi_clk); + return 125000000; /* arbitrary guess if no clock rate set */ +} + /** * axienet_calc_cr() - Calculate control register value * @lp: Device private data @@ -243,12 +250,9 @@ static u32 axienet_calc_cr(struct axienet_local *lp, u32 count, u32 usec) * the first packet. Otherwise leave at 0 to disable delay interrupt. */ if (count > 1) { - u64 clk_rate = 125000000; /* arbitrary guess if no clock rate set */ + u64 clk_rate = axienet_dma_rate(lp); u32 timer; - if (lp->axi_clk) - clk_rate = clk_get_rate(lp->axi_clk); - /* 1 Timeout Interval = 125 * (clock period of SG clock) */ timer = DIV64_U64_ROUND_CLOSEST((u64)usec * clk_rate, XAXIDMA_DELAY_SCALE); @@ -261,6 +265,23 @@ static u32 axienet_calc_cr(struct axienet_local *lp, u32 count, u32 usec) return cr; } +/** + * axienet_cr_params() - Extract coalesce parameters from the CR + * @lp: Device private data + * @cr: The control register to parse + * @count: Number of packets before an interrupt + * @usec: Idle time (in usec) before an interrupt + */ +static void axienet_coalesce_params(struct axienet_local *lp, u32 cr, + u32 *count, u32 *usec) +{ + u64 clk_rate = axienet_dma_rate(lp); + u64 timer = FIELD_GET(XAXIDMA_DELAY_MASK, cr); + + *count = FIELD_GET(XAXIDMA_COALESCE_MASK, cr); + *usec = DIV64_U64_ROUND_CLOSEST(timer * XAXIDMA_DELAY_SCALE, clk_rate); +} + /** * axienet_dma_start - Set up DMA registers and start DMA operation * @lp: Pointer to the axienet_local structure @@ -2095,11 +2116,21 @@ axienet_ethtools_get_coalesce(struct net_device *ndev, struct netlink_ext_ack *extack) { struct axienet_local *lp = netdev_priv(ndev); + u32 cr; - ecoalesce->rx_max_coalesced_frames = lp->coalesce_count_rx; - ecoalesce->rx_coalesce_usecs = lp->coalesce_usec_rx; - ecoalesce->tx_max_coalesced_frames = lp->coalesce_count_tx; - ecoalesce->tx_coalesce_usecs = lp->coalesce_usec_tx; + spin_lock_irq(&lp->rx_cr_lock); + cr = lp->rx_dma_cr; + spin_unlock_irq(&lp->rx_cr_lock); + axienet_coalesce_params(lp, cr, + &ecoalesce->rx_max_coalesced_frames, + &ecoalesce->rx_coalesce_usecs); + + spin_lock_irq(&lp->tx_cr_lock); + cr = lp->tx_dma_cr; + spin_unlock_irq(&lp->tx_cr_lock); + axienet_coalesce_params(lp, cr, + &ecoalesce->tx_max_coalesced_frames, + &ecoalesce->tx_coalesce_usecs); return 0; } @@ -2140,15 +2171,12 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, return -EINVAL; } - lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames; - lp->coalesce_usec_rx = ecoalesce->rx_coalesce_usecs; - lp->coalesce_count_tx = ecoalesce->tx_max_coalesced_frames; - lp->coalesce_usec_tx = ecoalesce->tx_coalesce_usecs; - - cr = axienet_calc_cr(lp, lp->coalesce_count_rx, lp->coalesce_usec_rx); + cr = axienet_calc_cr(lp, ecoalesce->rx_max_coalesced_frames, + ecoalesce->rx_coalesce_usecs); axienet_update_coalesce_rx(lp, cr, ~XAXIDMA_CR_RUNSTOP_MASK); - cr = axienet_calc_cr(lp, lp->coalesce_count_tx, lp->coalesce_usec_tx); + cr = axienet_calc_cr(lp, ecoalesce->tx_max_coalesced_frames, + ecoalesce->tx_coalesce_usecs); axienet_update_coalesce_tx(lp, cr, ~XAXIDMA_CR_RUNSTOP_MASK); return 0; } @@ -2936,14 +2964,10 @@ static int axienet_probe(struct platform_device *pdev) spin_lock_init(&lp->rx_cr_lock); spin_lock_init(&lp->tx_cr_lock); - lp->coalesce_count_rx = XAXIDMA_DFT_RX_THRESHOLD; - lp->coalesce_count_tx = XAXIDMA_DFT_TX_THRESHOLD; - lp->coalesce_usec_rx = XAXIDMA_DFT_RX_USEC; - lp->coalesce_usec_tx = XAXIDMA_DFT_TX_USEC; - lp->rx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_rx, - lp->coalesce_usec_rx); - lp->tx_dma_cr = axienet_calc_cr(lp, lp->coalesce_count_tx, - lp->coalesce_usec_tx); + lp->rx_dma_cr = axienet_calc_cr(lp, XAXIDMA_DFT_RX_THRESHOLD, + XAXIDMA_DFT_RX_USEC); + lp->tx_dma_cr = axienet_calc_cr(lp, XAXIDMA_DFT_TX_THRESHOLD, + XAXIDMA_DFT_TX_USEC); ret = axienet_mdio_setup(lp); if (ret) From patchwork Mon Sep 9 23:52:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Anderson X-Patchwork-Id: 13797712 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9590CECE58C for ; Mon, 9 Sep 2024 23:59:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=2HpjAZM+TWby3wVWVYyL+dHW5q5pMysAcY47I4DBh+M=; b=ohcW+f5BN7HThOvSmaBuz710PY /iLRhdJzHuYVpzDtM6MTUxZaEqMPh03xbwPXe7zx/mxbyz31KgPHvVq3/tS+Fvgr1wmIwJkYKc+4M aoNtl3Q/Y0sTiHxOF4oFJzi6k0p3RbTXKgEwbCZSAz+PPOihrAc4tSSqLrUF2ShjZybe/ACWUuegr QOABh7bbREAcaSMDRr57sjg9EpjbkgY0aMPz0VoziaaPDDIsgFjJ8ZWUaVxP9O5vtJycUDUWWu13l lUdm2jEzT9KZv0ui+C90CbLKEFN6O7prIyhVjJAzhAUr8at9+yhar9j8IVbIUkFhVX6oc4p4N02iM uTQN9f/w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoI4-00000003dnt-1CVC; Mon, 09 Sep 2024 23:59:28 +0000 Received: from out-186.mta1.migadu.com ([2001:41d0:203:375::ba]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1snoBG-00000003cKp-3EKA for linux-arm-kernel@lists.infradead.org; Mon, 09 Sep 2024 23:52:28 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1725925944; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2HpjAZM+TWby3wVWVYyL+dHW5q5pMysAcY47I4DBh+M=; b=P96N8hBCxqP3urN/33qiWa8ilJEjwRtbz+bE31uxrSllHTpCkFG4nUIT91EgDjoqZ5WzD9 CNES6j2VamHKzQ8MhejyZyBp+Zkbcq6XOxQKAm5+9NtZfYX+s3LvQSssNa3Z/Fw0oHzCWR 8s7H7eXDkDlmyJ3xzP7lZU7qA00D7po= From: Sean Anderson To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Radhey Shyam Pandey , netdev@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org, Michal Simek , linux-kernel@vger.kernel.org, Sean Anderson , Heng Qi Subject: [RFC PATCH net-next v2 6/6] net: xilinx: axienet: Enable adaptive IRQ coalescing with DIM Date: Mon, 9 Sep 2024 19:52:08 -0400 Message-Id: <20240909235208.1331065-7-sean.anderson@linux.dev> In-Reply-To: <20240909235208.1331065-1-sean.anderson@linux.dev> References: <20240909235208.1331065-1-sean.anderson@linux.dev> MIME-Version: 1.0 X-Migadu-Flow: FLOW_OUT X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240909_165226_975865_540DAA51 X-CRM114-Status: GOOD ( 33.68 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The default RX IRQ coalescing settings of one IRQ per packet can represent a significant CPU load. However, increasing the coalescing unilaterally can result in undesirable latency under low load. Adaptive IRQ coalescing with DIM offers a way to adjust the coalescing settings based on load. This device only supports "CQE" mode [1], where each packet resets the timer. Therefore, an interrupt is fired either when we receive coalesce_count_rx packets or when the interface is idle for coalesce_usec_rx. With this in mind, consider the following scenarios: Link saturated Here we want to set coalesce_count_rx to a large value, in order to coalesce more packets and reduce CPU load. coalesce_usec_rx should be set to at least the time for one packet. Otherwise the link will be "idle" and we will get an interrupt for each packet anyway. Bursts of packets Each burst should be coalesced into a single interrupt, although it may be prudent to reduce coalesce_count_rx for better latency. coalesce_usec_rx should be set to at least the time for one packet so bursts are coalesced. However, additional time beyond the packet time will just increase latency at the end of a burst. Sporadic packets Due to low load, we can set coalesce_count_rx to 1 in order to reduce latency to the minimum. coalesce_usec_rx does not matter in this case. Based on this analysis, I expected the CQE profiles to look something like usec = 0, pkts = 1 // Low load usec = 16, pkts = 4 usec = 16, pkts = 16 usec = 16, pkts = 64 usec = 16, pkts = 256 // High load Where usec is set to 16 to be a few us greater than the 12.3 us packet time of a 1500 MTU packet at 1 GBit/s. However, the CQE profile is instead usec = 2, pkts = 256 // Low load usec = 8, pkts = 128 usec = 16, pkts = 64 usec = 32, pkts = 64 usec = 64, pkts = 64 // High load I found this very surprising. The number of coalesced packets *decreases* as load increases. But as load increases we have more opportunities to coalesce packets without affecting latency as much. Additionally, the profile *increases* the usec as the load increases. But as load increases, the gaps between packets will tend to become smaller, making it possible to *decrease* usec for better latency at the end of a "burst". I consider the default CQE profile unsuitable for this NIC. Therefore, we use the first profile outlined in this commit instead. coalesce_usec_rx is set to 16 by default, but the user can customize it. This may be necessary if they are using jumbo frames. I think adjusting the profile times based on the link speed/mtu would be good improvement for generic DIM. In addition to the above profile problems, I noticed the following additional issues with DIM while testing: - DIM tends to "wander" when at low load, since the performance gradient is pretty flat. If you only have 10p/ms anyway then adjusting the coalescing settings will not affect throughput very much. - DIM takes a long time to adjust back to low indices when load is decreased following a period of high load. This is because it only re-evaluates its settings once every 64 interrupts. However, at low load 64 interrupts can be several seconds. Finally: performance. This patch increases receive throughput with iperf3 from 840 Mbits/sec to 938 Mbits/sec, decreases interrupts from 69920/sec to 316/sec, and decreases CPU utilization (4x Cortex-A53) from 43% to 9%. [1] Who names this stuff? Signed-off-by: Sean Anderson --- Heng, maybe you have some comments on DIM regarding the above? Changes in v2: - Don't take the RTNL in axienet_rx_dim_work to avoid deadlock. Instead, calculate a partial cr update that axienet_update_coalesce_rx can perform under a spin lock. - Use READ/WRITE_ONCE when accessing/modifying rx_irqs drivers/net/ethernet/xilinx/Kconfig | 1 + drivers/net/ethernet/xilinx/xilinx_axienet.h | 10 ++- .../net/ethernet/xilinx/xilinx_axienet_main.c | 80 +++++++++++++++++-- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 35d96c633a33..7502214cc7d5 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig @@ -28,6 +28,7 @@ config XILINX_AXI_EMAC depends on HAS_IOMEM depends on XILINX_DMA select PHYLINK + select DIMLIB help This driver supports the 10/100/1000 Ethernet from Xilinx for the AXI bus interface used in Xilinx Virtex FPGAs and Soc's. diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 33d05e55567e..b6604e354de7 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -9,6 +9,7 @@ #ifndef XILINX_AXIENET_H #define XILINX_AXIENET_H +#include #include #include #include @@ -123,8 +124,7 @@ /* Default TX/RX Threshold and delay timer values for SGDMA mode */ #define XAXIDMA_DFT_TX_THRESHOLD 24 #define XAXIDMA_DFT_TX_USEC 50 -#define XAXIDMA_DFT_RX_THRESHOLD 1 -#define XAXIDMA_DFT_RX_USEC 50 +#define XAXIDMA_DFT_RX_USEC 16 #define XAXIDMA_BD_CTRL_TXSOF_MASK 0x08000000 /* First tx packet */ #define XAXIDMA_BD_CTRL_TXEOF_MASK 0x04000000 /* Last tx packet */ @@ -484,6 +484,9 @@ struct skbuf_dma_descriptor { * @regs: Base address for the axienet_local device address space * @dma_regs: Base address for the axidma device address space * @napi_rx: NAPI RX control structure + * @rx_dim: DIM state for the receive queue + * @rx_irqs: Number of interrupts + * @rx_dim_enabled: Whether DIM is enabled or not * @rx_cr_lock: Lock protecting @rx_dma_cr, its register, and @rx_dma_started * @rx_dma_cr: Nominal content of RX DMA control register * @rx_dma_started: Set when RX DMA is started @@ -566,6 +569,9 @@ struct axienet_local { void __iomem *dma_regs; struct napi_struct napi_rx; + struct dim rx_dim; + bool rx_dim_enabled; + u16 rx_irqs; spinlock_t rx_cr_lock; u32 rx_dma_cr; bool rx_dma_started; diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index eb9600417d81..194ae87f534a 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1279,6 +1279,18 @@ static int axienet_rx_poll(struct napi_struct *napi, int budget) axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p); if (packets < budget && napi_complete_done(napi, packets)) { + if (READ_ONCE(lp->rx_dim_enabled)) { + struct dim_sample sample = { + .time = ktime_get(), + /* Safe because we are the only writer */ + .pkt_ctr = u64_stats_read(&lp->rx_packets), + .byte_ctr = u64_stats_read(&lp->rx_bytes), + .event_ctr = READ_ONCE(lp->rx_irqs), + }; + + net_dim(&lp->rx_dim, sample); + } + /* Re-enable RX completion interrupts. This should * cause an immediate interrupt if any RX packets are * already pending. @@ -1373,6 +1385,7 @@ static irqreturn_t axienet_rx_irq(int irq, void *_ndev) */ u32 cr; + WRITE_ONCE(lp->rx_irqs, READ_ONCE(lp->rx_irqs) + 1); spin_lock(&lp->rx_cr_lock); cr = lp->rx_dma_cr; cr &= ~(XAXIDMA_IRQ_IOC_MASK | XAXIDMA_IRQ_DELAY_MASK); @@ -1670,6 +1683,7 @@ static int axienet_open(struct net_device *ndev) if (lp->eth_irq > 0) free_irq(lp->eth_irq, ndev); err_phy: + cancel_work_sync(&lp->rx_dim.work); cancel_delayed_work_sync(&lp->stats_work); phylink_stop(lp->phylink); phylink_disconnect_phy(lp->phylink); @@ -1696,6 +1710,7 @@ static int axienet_stop(struct net_device *ndev) napi_disable(&lp->napi_rx); } + cancel_work_sync(&lp->rx_dim.work); cancel_delayed_work_sync(&lp->stats_work); phylink_stop(lp->phylink); @@ -2068,6 +2083,31 @@ static void axienet_update_coalesce_rx(struct axienet_local *lp, u32 cr, spin_unlock_irq(&lp->rx_cr_lock); } +/** + * axienet_dim_coalesce_count_rx() - RX coalesce count for DIM + * @lp: Device private data + */ +static u32 axienet_dim_coalesce_count_rx(struct axienet_local *lp) +{ + return 1 << (lp->rx_dim.profile_ix << 1); +} + +/** + * axienet_rx_dim_work() - Adjust RX DIM settings + * @work: The work struct + */ +static void axienet_rx_dim_work(struct work_struct *work) +{ + struct axienet_local *lp = + container_of(work, struct axienet_local, rx_dim.work); + u32 cr = axienet_calc_cr(lp, axienet_dim_coalesce_count_rx(lp), 0); + u32 mask = XAXIDMA_COALESCE_MASK | XAXIDMA_IRQ_IOC_MASK | + XAXIDMA_IRQ_ERROR_MASK; + + axienet_update_coalesce_rx(lp, cr, mask); + lp->rx_dim.state = DIM_START_MEASURE; +} + /** * axienet_set_cr_tx() - Set TX CR * @lp: Device private data @@ -2118,6 +2158,8 @@ axienet_ethtools_get_coalesce(struct net_device *ndev, struct axienet_local *lp = netdev_priv(ndev); u32 cr; + ecoalesce->use_adaptive_rx_coalesce = lp->rx_dim_enabled; + spin_lock_irq(&lp->rx_cr_lock); cr = lp->rx_dma_cr; spin_unlock_irq(&lp->rx_cr_lock); @@ -2154,7 +2196,9 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, struct netlink_ext_ack *extack) { struct axienet_local *lp = netdev_priv(ndev); - u32 cr; + bool new_dim = ecoalesce->use_adaptive_rx_coalesce; + bool old_dim = lp->rx_dim_enabled; + u32 cr, mask = ~XAXIDMA_CR_RUNSTOP_MASK; if (!ecoalesce->rx_max_coalesced_frames || !ecoalesce->tx_max_coalesced_frames) { @@ -2162,7 +2206,7 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, return -EINVAL; } - if ((ecoalesce->rx_max_coalesced_frames > 1 && + if (((ecoalesce->rx_max_coalesced_frames > 1 || new_dim) && !ecoalesce->rx_coalesce_usecs) || (ecoalesce->tx_max_coalesced_frames > 1 && !ecoalesce->tx_coalesce_usecs)) { @@ -2171,9 +2215,27 @@ axienet_ethtools_set_coalesce(struct net_device *ndev, return -EINVAL; } - cr = axienet_calc_cr(lp, ecoalesce->rx_max_coalesced_frames, - ecoalesce->rx_coalesce_usecs); - axienet_update_coalesce_rx(lp, cr, ~XAXIDMA_CR_RUNSTOP_MASK); + if (new_dim && !old_dim) { + cr = axienet_calc_cr(lp, axienet_dim_coalesce_count_rx(lp), + ecoalesce->rx_coalesce_usecs); + } else if (!new_dim) { + if (old_dim) { + WRITE_ONCE(lp->rx_dim_enabled, false); + napi_synchronize(&lp->napi_rx); + flush_work(&lp->rx_dim.work); + } + + cr = axienet_calc_cr(lp, ecoalesce->rx_max_coalesced_frames, + ecoalesce->rx_coalesce_usecs); + } else { + /* Dummy value for count just to calculate timer */ + cr = axienet_calc_cr(lp, 2, ecoalesce->rx_coalesce_usecs); + mask = XAXIDMA_DELAY_MASK | XAXIDMA_IRQ_DELAY_MASK; + } + + axienet_update_coalesce_rx(lp, cr, mask); + if (new_dim && !old_dim) + WRITE_ONCE(lp->rx_dim_enabled, true); cr = axienet_calc_cr(lp, ecoalesce->tx_max_coalesced_frames, ecoalesce->tx_coalesce_usecs); @@ -2415,7 +2477,8 @@ axienet_ethtool_get_rmon_stats(struct net_device *dev, static const struct ethtool_ops axienet_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES | - ETHTOOL_COALESCE_USECS, + ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_USE_ADAPTIVE_RX, .get_drvinfo = axienet_ethtools_get_drvinfo, .get_regs_len = axienet_ethtools_get_regs_len, .get_regs = axienet_ethtools_get_regs, @@ -2964,7 +3027,10 @@ static int axienet_probe(struct platform_device *pdev) spin_lock_init(&lp->rx_cr_lock); spin_lock_init(&lp->tx_cr_lock); - lp->rx_dma_cr = axienet_calc_cr(lp, XAXIDMA_DFT_RX_THRESHOLD, + INIT_WORK(&lp->rx_dim.work, axienet_rx_dim_work); + lp->rx_dim_enabled = true; + lp->rx_dim.profile_ix = 1; + lp->rx_dma_cr = axienet_calc_cr(lp, axienet_dim_coalesce_count_rx(lp), XAXIDMA_DFT_RX_USEC); lp->tx_dma_cr = axienet_calc_cr(lp, XAXIDMA_DFT_TX_THRESHOLD, XAXIDMA_DFT_TX_USEC);