From nobody Mon May 11 12:11:17 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A8C34C433FE for ; Fri, 8 Apr 2022 07:01:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229665AbiDHHDR (ORCPT ); Fri, 8 Apr 2022 03:03:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47378 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229542AbiDHHC7 (ORCPT ); Fri, 8 Apr 2022 03:02:59 -0400 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E30EA6C94D; Fri, 8 Apr 2022 00:00:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1649401256; x=1680937256; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=WHXdICJcA+QrI/9tUJw23cxnslvJWuCZDaHexLxZLSE=; b=S5tU1tNTt82cF0yKJn5PFqY1QCIqecJbmUBEsn/b3Z/kMk073sScxsFH YR0VNSXudQP1QyQU4b0DKkdcOe09N2y/lutGlkT/hYRVEb34p1R735e2O 0wX19ZWgS2Qe/9l6t0yiKUsejoJ1tBxlG311K00qE3ljRxbGiczATbITs 0qMqAxYlUzO7GSnIzmTNIZgj+Pz8yZZb+5ts01EoDQfli2Xm75aHQV/rd 5bPJeq8JxN8OYDo7dA2xois4HHNRxvuCOOYERTQvyr5VxZLTYAExINsMi lnpRXmbL2KrWpwrR5GYMpAp4/2VO1nni54iyfjSMJQAYBzkoBreFNScar g==; X-IronPort-AV: E=Sophos;i="5.90,244,1643698800"; d="scan'208";a="159826207" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa3.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 08 Apr 2022 00:00:56 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.17; Fri, 8 Apr 2022 00:00:56 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2375.17 via Frontend Transport; Fri, 8 Apr 2022 00:00:54 -0700 From: Horatiu Vultur To: , CC: , , , , , Horatiu Vultur Subject: [PATCH net-next v4 1/4] net: lan966x: Add registers that are used for FDMA. Date: Fri, 8 Apr 2022 09:03:54 +0200 Message-ID: <20220408070357.559899-2-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220408070357.559899-1-horatiu.vultur@microchip.com> References: <20220408070357.559899-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add the registers that are used to configure the FDMA. Signed-off-by: Horatiu Vultur Tested-by: Michael Walle # on kontron-kswitch-d10 --- .../ethernet/microchip/lan966x/lan966x_main.c | 1 + .../ethernet/microchip/lan966x/lan966x_regs.h | 106 ++++++++++++++++++ 2 files changed, 107 insertions(+) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.c index 0765064d2845..3e22bfcd4409 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -43,6 +43,7 @@ struct lan966x_main_io_resource { =20 static const struct lan966x_main_io_resource lan966x_main_iomap[] =3D { { TARGET_CPU, 0xc0000, 0 }, /* 0xe00c0000 */ + { TARGET_FDMA, 0xc0400, 0 }, /* 0xe00c0400 */ { TARGET_ORG, 0, 1 }, /* 0xe2000000 */ { TARGET_GCB, 0x4000, 1 }, /* 0xe2004000 */ { TARGET_QS, 0x8000, 1 }, /* 0xe2008000 */ diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/driver= s/net/ethernet/microchip/lan966x/lan966x_regs.h index 0c0b3e173d53..2f59285bef29 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h @@ -17,6 +17,7 @@ enum lan966x_target { TARGET_CHIP_TOP =3D 5, TARGET_CPU =3D 6, TARGET_DEV =3D 13, + TARGET_FDMA =3D 21, TARGET_GCB =3D 27, TARGET_ORG =3D 36, TARGET_PTP =3D 41, @@ -578,6 +579,111 @@ enum lan966x_target { #define DEV_PCS1G_STICKY_LINK_DOWN_STICKY_GET(x)\ FIELD_GET(DEV_PCS1G_STICKY_LINK_DOWN_STICKY, x) =20 +/* FDMA:FDMA:FDMA_CH_ACTIVATE */ +#define FDMA_CH_ACTIVATE __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 0= , 0, 1, 4) + +#define FDMA_CH_ACTIVATE_CH_ACTIVATE GENMASK(7, 0) +#define FDMA_CH_ACTIVATE_CH_ACTIVATE_SET(x)\ + FIELD_PREP(FDMA_CH_ACTIVATE_CH_ACTIVATE, x) +#define FDMA_CH_ACTIVATE_CH_ACTIVATE_GET(x)\ + FIELD_GET(FDMA_CH_ACTIVATE_CH_ACTIVATE, x) + +/* FDMA:FDMA:FDMA_CH_RELOAD */ +#define FDMA_CH_RELOAD __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 4= , 0, 1, 4) + +#define FDMA_CH_RELOAD_CH_RELOAD GENMASK(7, 0) +#define FDMA_CH_RELOAD_CH_RELOAD_SET(x)\ + FIELD_PREP(FDMA_CH_RELOAD_CH_RELOAD, x) +#define FDMA_CH_RELOAD_CH_RELOAD_GET(x)\ + FIELD_GET(FDMA_CH_RELOAD_CH_RELOAD, x) + +/* FDMA:FDMA:FDMA_CH_DISABLE */ +#define FDMA_CH_DISABLE __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 8= , 0, 1, 4) + +#define FDMA_CH_DISABLE_CH_DISABLE GENMASK(7, 0) +#define FDMA_CH_DISABLE_CH_DISABLE_SET(x)\ + FIELD_PREP(FDMA_CH_DISABLE_CH_DISABLE, x) +#define FDMA_CH_DISABLE_CH_DISABLE_GET(x)\ + FIELD_GET(FDMA_CH_DISABLE_CH_DISABLE, x) + +/* FDMA:FDMA:FDMA_CH_DB_DISCARD */ +#define FDMA_CH_DB_DISCARD __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 1= 6, 0, 1, 4) + +#define FDMA_CH_DB_DISCARD_DB_DISCARD GENMASK(7, 0) +#define FDMA_CH_DB_DISCARD_DB_DISCARD_SET(x)\ + FIELD_PREP(FDMA_CH_DB_DISCARD_DB_DISCARD, x) +#define FDMA_CH_DB_DISCARD_DB_DISCARD_GET(x)\ + FIELD_GET(FDMA_CH_DB_DISCARD_DB_DISCARD, x) + +/* FDMA:FDMA:FDMA_DCB_LLP */ +#define FDMA_DCB_LLP(r) __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 5= 2, r, 8, 4) + +/* FDMA:FDMA:FDMA_DCB_LLP1 */ +#define FDMA_DCB_LLP1(r) __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 8= 4, r, 8, 4) + +/* FDMA:FDMA:FDMA_CH_ACTIVE */ +#define FDMA_CH_ACTIVE __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 1= 80, 0, 1, 4) + +/* FDMA:FDMA:FDMA_CH_CFG */ +#define FDMA_CH_CFG(r) __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 2= 24, r, 8, 4) + +#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY BIT(4) +#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(x)\ + FIELD_PREP(FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY, x) +#define FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_GET(x)\ + FIELD_GET(FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY, x) + +#define FDMA_CH_CFG_CH_INJ_PORT BIT(3) +#define FDMA_CH_CFG_CH_INJ_PORT_SET(x)\ + FIELD_PREP(FDMA_CH_CFG_CH_INJ_PORT, x) +#define FDMA_CH_CFG_CH_INJ_PORT_GET(x)\ + FIELD_GET(FDMA_CH_CFG_CH_INJ_PORT, x) + +#define FDMA_CH_CFG_CH_DCB_DB_CNT GENMASK(2, 1) +#define FDMA_CH_CFG_CH_DCB_DB_CNT_SET(x)\ + FIELD_PREP(FDMA_CH_CFG_CH_DCB_DB_CNT, x) +#define FDMA_CH_CFG_CH_DCB_DB_CNT_GET(x)\ + FIELD_GET(FDMA_CH_CFG_CH_DCB_DB_CNT, x) + +#define FDMA_CH_CFG_CH_MEM BIT(0) +#define FDMA_CH_CFG_CH_MEM_SET(x)\ + FIELD_PREP(FDMA_CH_CFG_CH_MEM, x) +#define FDMA_CH_CFG_CH_MEM_GET(x)\ + FIELD_GET(FDMA_CH_CFG_CH_MEM, x) + +/* FDMA:FDMA:FDMA_PORT_CTRL */ +#define FDMA_PORT_CTRL(r) __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 3= 76, r, 2, 4) + +#define FDMA_PORT_CTRL_INJ_STOP BIT(4) +#define FDMA_PORT_CTRL_INJ_STOP_SET(x)\ + FIELD_PREP(FDMA_PORT_CTRL_INJ_STOP, x) +#define FDMA_PORT_CTRL_INJ_STOP_GET(x)\ + FIELD_GET(FDMA_PORT_CTRL_INJ_STOP, x) + +#define FDMA_PORT_CTRL_XTR_STOP BIT(2) +#define FDMA_PORT_CTRL_XTR_STOP_SET(x)\ + FIELD_PREP(FDMA_PORT_CTRL_XTR_STOP, x) +#define FDMA_PORT_CTRL_XTR_STOP_GET(x)\ + FIELD_GET(FDMA_PORT_CTRL_XTR_STOP, x) + +/* FDMA:FDMA:FDMA_INTR_DB */ +#define FDMA_INTR_DB __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 3= 92, 0, 1, 4) + +/* FDMA:FDMA:FDMA_INTR_DB_ENA */ +#define FDMA_INTR_DB_ENA __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 3= 96, 0, 1, 4) + +#define FDMA_INTR_DB_ENA_INTR_DB_ENA GENMASK(7, 0) +#define FDMA_INTR_DB_ENA_INTR_DB_ENA_SET(x)\ + FIELD_PREP(FDMA_INTR_DB_ENA_INTR_DB_ENA, x) +#define FDMA_INTR_DB_ENA_INTR_DB_ENA_GET(x)\ + FIELD_GET(FDMA_INTR_DB_ENA_INTR_DB_ENA, x) + +/* FDMA:FDMA:FDMA_INTR_ERR */ +#define FDMA_INTR_ERR __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 4= 00, 0, 1, 4) + +/* FDMA:FDMA:FDMA_ERRORS */ +#define FDMA_ERRORS __REG(TARGET_FDMA, 0, 1, 8, 0, 1, 428, 4= 12, 0, 1, 4) + /* PTP:PTP_CFG:PTP_DOM_CFG */ #define PTP_DOM_CFG __REG(TARGET_PTP, 0, 1, 512, 0, 1, 16, 1= 2, 0, 1, 4) =20 --=20 2.33.0 From nobody Mon May 11 12:11:17 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 917AFC433F5 for ; Fri, 8 Apr 2022 07:01:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229666AbiDHHDW (ORCPT ); Fri, 8 Apr 2022 03:03:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47548 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229572AbiDHHDB (ORCPT ); Fri, 8 Apr 2022 03:03:01 -0400 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A69A0710F7; Fri, 8 Apr 2022 00:00:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1649401259; x=1680937259; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=OHrFyBYh7zOAExoP5vQt21N8TDpyzsvJW0IvSZrB/L0=; b=D5FgirEuc2WPRiX0q/Ggiqrfb25+Bvwoo9engmM28rIBHJqhosGr1FV4 vmqKzcNEwVFdy3d4yyxSr3Ut4woeMEGYIkI+SLBpn1LGDZKnU4D9q1Oyu nQ10xZKFIecezGyOTLDL8dwNM8VrNfkMfPjBpxh8WJ52+mWEbJ7PK/3t3 9lFn+PSekjkAC4vOvEJnUmLNg9NFzBdGbiGt3VzFXj1xCpzKB0zSZnvh5 gvJdpNp/GZnwwM56XM16LvLTw5+ZxQpC3aewUu+r+BUR3kCw3saOsw3Y+ iW/OcQaDgM+5As3o7eRxsBhZ8sar03I4ZwKjqW5jczY5JnCZV9oyWaISR g==; X-IronPort-AV: E=Sophos;i="5.90,244,1643698800"; d="scan'208";a="168914991" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa1.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 08 Apr 2022 00:00:59 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.17; Fri, 8 Apr 2022 00:00:58 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2375.17 via Frontend Transport; Fri, 8 Apr 2022 00:00:56 -0700 From: Horatiu Vultur To: , CC: , , , , , Horatiu Vultur Subject: [PATCH net-next v4 2/4] net: lan966x: Expose functions that are needed by FDMA Date: Fri, 8 Apr 2022 09:03:55 +0200 Message-ID: <20220408070357.559899-3-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220408070357.559899-1-horatiu.vultur@microchip.com> References: <20220408070357.559899-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Expose the following functions 'lan966x_hw_offload', 'lan966x_ifh_get_src_port' and 'lan966x_ifh_get_timestamp' in lan966x_main.h so they can be accessed by FDMA. Signed-off-by: Horatiu Vultur Tested-by: Michael Walle # on kontron-kswitch-d10 --- drivers/net/ethernet/microchip/lan966x/lan966x_main.c | 10 +++------- drivers/net/ethernet/microchip/lan966x/lan966x_main.h | 8 ++++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.c index 3e22bfcd4409..03f0d149a80b 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -24,9 +24,6 @@ #define XTR_NOT_READY 0x07000080U #define XTR_VALID_BYTES(x) (4 - (((x) >> 24) & 3)) =20 -#define READL_SLEEP_US 10 -#define READL_TIMEOUT_US 100000000 - #define IO_RANGES 2 =20 static const struct of_device_id lan966x_match[] =3D { @@ -433,8 +430,7 @@ bool lan966x_netdevice_check(const struct net_device *d= ev) return dev->netdev_ops =3D=3D &lan966x_port_netdev_ops; } =20 -static bool lan966x_hw_offload(struct lan966x *lan966x, u32 port, - struct sk_buff *skb) +bool lan966x_hw_offload(struct lan966x *lan966x, u32 port, struct sk_buff = *skb) { u32 val; =20 @@ -515,7 +511,7 @@ static int lan966x_rx_frame_word(struct lan966x *lan966= x, u8 grp, u32 *rval) } } =20 -static void lan966x_ifh_get_src_port(void *ifh, u64 *src_port) +void lan966x_ifh_get_src_port(void *ifh, u64 *src_port) { packing(ifh, src_port, IFH_POS_SRCPORT + IFH_WID_SRCPORT - 1, IFH_POS_SRCPORT, IFH_LEN * 4, UNPACK, 0); @@ -527,7 +523,7 @@ static void lan966x_ifh_get_len(void *ifh, u64 *len) IFH_POS_LEN, IFH_LEN * 4, UNPACK, 0); } =20 -static void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp) +void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp) { packing(ifh, timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, IFH_POS_TIMESTAMP, IFH_LEN * 4, UNPACK, 0); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.h index ae282da1da74..b692c612f235 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -17,6 +17,9 @@ #define TABLE_UPDATE_SLEEP_US 10 #define TABLE_UPDATE_TIMEOUT_US 100000 =20 +#define READL_SLEEP_US 10 +#define READL_TIMEOUT_US 100000000 + #define LAN966X_BUFFER_CELL_SZ 64 #define LAN966X_BUFFER_MEMORY (160 * 1024) #define LAN966X_BUFFER_MIN_SZ 60 @@ -195,6 +198,11 @@ bool lan966x_netdevice_check(const struct net_device *= dev); void lan966x_register_notifier_blocks(void); void lan966x_unregister_notifier_blocks(void); =20 +bool lan966x_hw_offload(struct lan966x *lan966x, u32 port, struct sk_buff = *skb); + +void lan966x_ifh_get_src_port(void *ifh, u64 *src_port); +void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp); + void lan966x_stats_get(struct net_device *dev, struct rtnl_link_stats64 *stats); int lan966x_stats_init(struct lan966x *lan966x); --=20 2.33.0 From nobody Mon May 11 12:11:17 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 860CAC433EF for ; Fri, 8 Apr 2022 07:01:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229693AbiDHHD0 (ORCPT ); Fri, 8 Apr 2022 03:03:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47882 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229618AbiDHHDF (ORCPT ); Fri, 8 Apr 2022 03:03:05 -0400 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4CF51710F7; Fri, 8 Apr 2022 00:01:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1649401262; x=1680937262; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5NnR2bvRGZRlUQgQdhfaWpkHJs8BIS/WmKQNsNkhtJA=; b=qrdK8A6Hltz1WAKzCCm32mbPLJPgO8CMDKv56aD6f4/WJnAbVHAZesb3 kdApUkpoNPQF7acAipkIXyxN4ogTwt/Sk8r558pUPpiG7zS6Ccn9f8cVE Xr+/3CGpX5Q+A+BukbemGbYvk7vSYyWQHonxA2+pXKQW7qX8lHSXRjoAo 9wsHfQBsJA1XvMHECihRQHYSuTieztFpGGRJniJKQ4aGrGrQfQxjWQZXS aZDnpZVkeLC9bIVt+dQ0mLcGLaorTO2vm/7/3/CAmK/OAlDnTVV9YMv65 BXV3zbhGzkfSdNl78HmKmCIiqwNHEYJW1mHXLz/B3pASlWHdjvUNEE5+i Q==; X-IronPort-AV: E=Sophos;i="5.90,244,1643698800"; d="scan'208";a="159397628" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 08 Apr 2022 00:01:02 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.17; Fri, 8 Apr 2022 00:01:01 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2375.17 via Frontend Transport; Fri, 8 Apr 2022 00:00:59 -0700 From: Horatiu Vultur To: , CC: , , , , , Horatiu Vultur Subject: [PATCH net-next v4 3/4] net: lan966x: Add FDMA functionality Date: Fri, 8 Apr 2022 09:03:56 +0200 Message-ID: <20220408070357.559899-4-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220408070357.559899-1-horatiu.vultur@microchip.com> References: <20220408070357.559899-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Ethernet frames can be extracted or injected to or from the device's DDR memory. There is one channel for injection and one channel for extraction. Each of these channels contain a linked list of DCBs which contains DB. The DCB contains only 1 DB for both the injection and extraction. Each DB contains a frame. Every time when a frame is received or transmitted an interrupt is generated. It is not possible to use both the FDMA and the manual injection/extraction of the frames. Therefore the FDMA has priority over the manual because of better performance values. FDMA: iperf -c 192.168.1.1 [ 5] 0.00-10.02 sec 420 MBytes 352 Mbits/sec 0 sender [ 5] 0.00-10.03 sec 420 MBytes 351 Mbits/sec receiver iperf -c 192.168.1.1 -R [ 5] 0.00-10.01 sec 528 MBytes 442 Mbits/sec 0 sender [ 5] 0.00-10.00 sec 524 MBytes 440 Mbits/sec receiver Manual: iperf -c 192.168.1.1 [ 5] 0.00-10.02 sec 93.8 MBytes 78.5 Mbits/sec 0 sender [ 5] 0.00-10.03 sec 93.8 MBytes 78.4 Mbits/sec receiver ipers -c 192.168.1.1 -R [ 5] 0.00-10.03 sec 121 MBytes 101 Mbits/sec 0 sender [ 5] 0.00-10.01 sec 118 MBytes 99.0 Mbits/sec receiver Signed-off-by: Horatiu Vultur Tested-by: Michael Walle # on kontron-kswitch-d10 --- .../net/ethernet/microchip/lan966x/Makefile | 2 +- .../ethernet/microchip/lan966x/lan966x_fdma.c | 708 ++++++++++++++++++ .../ethernet/microchip/lan966x/lan966x_main.c | 34 +- .../ethernet/microchip/lan966x/lan966x_main.h | 108 +++ .../ethernet/microchip/lan966x/lan966x_port.c | 3 + 5 files changed, 851 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c diff --git a/drivers/net/ethernet/microchip/lan966x/Makefile b/drivers/net/= ethernet/microchip/lan966x/Makefile index a9ffc719aa0e..fd2e0ebb2427 100644 --- a/drivers/net/ethernet/microchip/lan966x/Makefile +++ b/drivers/net/ethernet/microchip/lan966x/Makefile @@ -8,4 +8,4 @@ obj-$(CONFIG_LAN966X_SWITCH) +=3D lan966x-switch.o lan966x-switch-objs :=3D lan966x_main.o lan966x_phylink.o lan966x_port.o \ lan966x_mac.o lan966x_ethtool.o lan966x_switchdev.o \ lan966x_vlan.o lan966x_fdb.o lan966x_mdb.o \ - lan966x_ptp.o + lan966x_ptp.o lan966x_fdma.o diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_fdma.c new file mode 100644 index 000000000000..f5fdb7455a41 --- /dev/null +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -0,0 +1,708 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include "lan966x_main.h" + +static int lan966x_fdma_channel_active(struct lan966x *lan966x) +{ + return lan_rd(lan966x, FDMA_CH_ACTIVE); +} + +static struct page *lan966x_fdma_rx_alloc_page(struct lan966x_rx *rx, + struct lan966x_db *db) +{ + struct lan966x *lan966x =3D rx->lan966x; + dma_addr_t dma_addr; + struct page *page; + + page =3D dev_alloc_pages(rx->page_order); + if (unlikely(!page)) + return NULL; + + dma_addr =3D dma_map_page(lan966x->dev, page, 0, + PAGE_SIZE << rx->page_order, + DMA_FROM_DEVICE); + if (unlikely(dma_mapping_error(lan966x->dev, dma_addr))) + goto free_page; + + db->dataptr =3D dma_addr; + + return page; + +free_page: + __free_pages(page, rx->page_order); + return NULL; +} + +static void lan966x_fdma_rx_free_pages(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + struct lan966x_rx_dcb *dcb; + struct lan966x_db *db; + int i, j; + + for (i =3D 0; i < FDMA_DCB_MAX; ++i) { + dcb =3D &rx->dcbs[i]; + + for (j =3D 0; j < FDMA_RX_DCB_MAX_DBS; ++j) { + db =3D &dcb->db[j]; + dma_unmap_single(lan966x->dev, + (dma_addr_t)db->dataptr, + PAGE_SIZE << rx->page_order, + DMA_FROM_DEVICE); + __free_pages(rx->page[i][j], rx->page_order); + } + } +} + +static void lan966x_fdma_rx_add_dcb(struct lan966x_rx *rx, + struct lan966x_rx_dcb *dcb, + u64 nextptr) +{ + struct lan966x_db *db; + int i; + + for (i =3D 0; i < FDMA_RX_DCB_MAX_DBS; ++i) { + db =3D &dcb->db[i]; + db->status =3D FDMA_DCB_STATUS_INTR; + } + + dcb->nextptr =3D FDMA_DCB_INVALID_DATA; + dcb->info =3D FDMA_DCB_INFO_DATAL(PAGE_SIZE << rx->page_order); + + rx->last_entry->nextptr =3D nextptr; + rx->last_entry =3D dcb; +} + +static int lan966x_fdma_rx_alloc(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + struct lan966x_rx_dcb *dcb; + struct lan966x_db *db; + struct page *page; + int i, j; + int size; + + /* calculate how many pages are needed to allocate the dcbs */ + size =3D sizeof(struct lan966x_rx_dcb) * FDMA_DCB_MAX; + size =3D ALIGN(size, PAGE_SIZE); + + rx->dcbs =3D dma_alloc_coherent(lan966x->dev, size, &rx->dma, GFP_KERNEL); + if (!rx->dcbs) + return -ENOMEM; + + rx->last_entry =3D rx->dcbs; + rx->db_index =3D 0; + rx->dcb_index =3D 0; + + /* Now for each dcb allocate the dbs */ + for (i =3D 0; i < FDMA_DCB_MAX; ++i) { + dcb =3D &rx->dcbs[i]; + dcb->info =3D 0; + + /* For each db allocate a page and map it to the DB dataptr. */ + for (j =3D 0; j < FDMA_RX_DCB_MAX_DBS; ++j) { + db =3D &dcb->db[j]; + page =3D lan966x_fdma_rx_alloc_page(rx, db); + if (!page) + return -ENOMEM; + + db->status =3D 0; + rx->page[i][j] =3D page; + } + + lan966x_fdma_rx_add_dcb(rx, dcb, rx->dma + sizeof(*dcb) * i); + } + + return 0; +} + +static void lan966x_fdma_rx_free(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + u32 size; + + /* Now it is possible to do the cleanup of dcb */ + size =3D sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX; + size =3D ALIGN(size, PAGE_SIZE); + dma_free_coherent(lan966x->dev, size, rx->dcbs, rx->dma); +} + +static void lan966x_fdma_rx_start(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + u32 mask; + + /* When activating a channel, first is required to write the first DCB + * address and then to activate it + */ + lan_wr(lower_32_bits((u64)rx->dma), lan966x, + FDMA_DCB_LLP(rx->channel_id)); + lan_wr(upper_32_bits((u64)rx->dma), lan966x, + FDMA_DCB_LLP1(rx->channel_id)); + + lan_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_RX_DCB_MAX_DBS) | + FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) | + FDMA_CH_CFG_CH_INJ_PORT_SET(0) | + FDMA_CH_CFG_CH_MEM_SET(1), + lan966x, FDMA_CH_CFG(rx->channel_id)); + + /* Start fdma */ + lan_rmw(FDMA_PORT_CTRL_XTR_STOP_SET(0), + FDMA_PORT_CTRL_XTR_STOP, + lan966x, FDMA_PORT_CTRL(0)); + + /* Enable interrupts */ + mask =3D lan_rd(lan966x, FDMA_INTR_DB_ENA); + mask =3D FDMA_INTR_DB_ENA_INTR_DB_ENA_GET(mask); + mask |=3D BIT(rx->channel_id); + lan_rmw(FDMA_INTR_DB_ENA_INTR_DB_ENA_SET(mask), + FDMA_INTR_DB_ENA_INTR_DB_ENA, + lan966x, FDMA_INTR_DB_ENA); + + /* Activate the channel */ + lan_rmw(FDMA_CH_ACTIVATE_CH_ACTIVATE_SET(BIT(rx->channel_id)), + FDMA_CH_ACTIVATE_CH_ACTIVATE, + lan966x, FDMA_CH_ACTIVATE); +} + +static void lan966x_fdma_rx_disable(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + u32 val; + + /* Disable the channel */ + lan_rmw(FDMA_CH_DISABLE_CH_DISABLE_SET(BIT(rx->channel_id)), + FDMA_CH_DISABLE_CH_DISABLE, + lan966x, FDMA_CH_DISABLE); + + readx_poll_timeout_atomic(lan966x_fdma_channel_active, lan966x, + val, !(val & BIT(rx->channel_id)), + READL_SLEEP_US, READL_TIMEOUT_US); + + lan_rmw(FDMA_CH_DB_DISCARD_DB_DISCARD_SET(BIT(rx->channel_id)), + FDMA_CH_DB_DISCARD_DB_DISCARD, + lan966x, FDMA_CH_DB_DISCARD); +} + +static void lan966x_fdma_rx_reload(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + + lan_rmw(FDMA_CH_RELOAD_CH_RELOAD_SET(BIT(rx->channel_id)), + FDMA_CH_RELOAD_CH_RELOAD, + lan966x, FDMA_CH_RELOAD); +} + +static void lan966x_fdma_tx_add_dcb(struct lan966x_tx *tx, + struct lan966x_tx_dcb *dcb) +{ + dcb->nextptr =3D FDMA_DCB_INVALID_DATA; + dcb->info =3D 0; +} + +static int lan966x_fdma_tx_alloc(struct lan966x_tx *tx) +{ + struct lan966x *lan966x =3D tx->lan966x; + struct lan966x_tx_dcb *dcb; + struct lan966x_db *db; + int size; + int i, j; + + tx->dcbs_buf =3D kcalloc(FDMA_DCB_MAX, sizeof(struct lan966x_tx_dcb_buf), + GFP_KERNEL); + if (!tx->dcbs_buf) + return -ENOMEM; + + /* calculate how many pages are needed to allocate the dcbs */ + size =3D sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX; + size =3D ALIGN(size, PAGE_SIZE); + tx->dcbs =3D dma_alloc_coherent(lan966x->dev, size, &tx->dma, GFP_KERNEL); + if (!tx->dcbs) + goto out; + + /* Now for each dcb allocate the db */ + for (i =3D 0; i < FDMA_DCB_MAX; ++i) { + dcb =3D &tx->dcbs[i]; + + for (j =3D 0; j < FDMA_TX_DCB_MAX_DBS; ++j) { + db =3D &dcb->db[j]; + db->dataptr =3D 0; + db->status =3D 0; + } + + lan966x_fdma_tx_add_dcb(tx, dcb); + } + + return 0; + +out: + kfree(tx->dcbs_buf); + return -ENOMEM; +} + +static void lan966x_fdma_tx_free(struct lan966x_tx *tx) +{ + struct lan966x *lan966x =3D tx->lan966x; + int size; + + kfree(tx->dcbs_buf); + + size =3D sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX; + size =3D ALIGN(size, PAGE_SIZE); + dma_free_coherent(lan966x->dev, size, tx->dcbs, tx->dma); +} + +static void lan966x_fdma_tx_activate(struct lan966x_tx *tx) +{ + struct lan966x *lan966x =3D tx->lan966x; + u32 mask; + + /* When activating a channel, first is required to write the first DCB + * address and then to activate it + */ + lan_wr(lower_32_bits((u64)tx->dma), lan966x, + FDMA_DCB_LLP(tx->channel_id)); + lan_wr(upper_32_bits((u64)tx->dma), lan966x, + FDMA_DCB_LLP1(tx->channel_id)); + + lan_wr(FDMA_CH_CFG_CH_DCB_DB_CNT_SET(FDMA_TX_DCB_MAX_DBS) | + FDMA_CH_CFG_CH_INTR_DB_EOF_ONLY_SET(1) | + FDMA_CH_CFG_CH_INJ_PORT_SET(0) | + FDMA_CH_CFG_CH_MEM_SET(1), + lan966x, FDMA_CH_CFG(tx->channel_id)); + + /* Start fdma */ + lan_rmw(FDMA_PORT_CTRL_INJ_STOP_SET(0), + FDMA_PORT_CTRL_INJ_STOP, + lan966x, FDMA_PORT_CTRL(0)); + + /* Enable interrupts */ + mask =3D lan_rd(lan966x, FDMA_INTR_DB_ENA); + mask =3D FDMA_INTR_DB_ENA_INTR_DB_ENA_GET(mask); + mask |=3D BIT(tx->channel_id); + lan_rmw(FDMA_INTR_DB_ENA_INTR_DB_ENA_SET(mask), + FDMA_INTR_DB_ENA_INTR_DB_ENA, + lan966x, FDMA_INTR_DB_ENA); + + /* Activate the channel */ + lan_rmw(FDMA_CH_ACTIVATE_CH_ACTIVATE_SET(BIT(tx->channel_id)), + FDMA_CH_ACTIVATE_CH_ACTIVATE, + lan966x, FDMA_CH_ACTIVATE); +} + +static void lan966x_fdma_tx_disable(struct lan966x_tx *tx) +{ + struct lan966x *lan966x =3D tx->lan966x; + u32 val; + + /* Disable the channel */ + lan_rmw(FDMA_CH_DISABLE_CH_DISABLE_SET(BIT(tx->channel_id)), + FDMA_CH_DISABLE_CH_DISABLE, + lan966x, FDMA_CH_DISABLE); + + readx_poll_timeout_atomic(lan966x_fdma_channel_active, lan966x, + val, !(val & BIT(tx->channel_id)), + READL_SLEEP_US, READL_TIMEOUT_US); + + lan_rmw(FDMA_CH_DB_DISCARD_DB_DISCARD_SET(BIT(tx->channel_id)), + FDMA_CH_DB_DISCARD_DB_DISCARD, + lan966x, FDMA_CH_DB_DISCARD); + + tx->activated =3D false; +} + +static void lan966x_fdma_tx_reload(struct lan966x_tx *tx) +{ + struct lan966x *lan966x =3D tx->lan966x; + + /* Write the registers to reload the channel */ + lan_rmw(FDMA_CH_RELOAD_CH_RELOAD_SET(BIT(tx->channel_id)), + FDMA_CH_RELOAD_CH_RELOAD, + lan966x, FDMA_CH_RELOAD); +} + +static void lan966x_fdma_wakeup_netdev(struct lan966x *lan966x) +{ + struct lan966x_port *port; + int i; + + for (i =3D 0; i < lan966x->num_phys_ports; ++i) { + port =3D lan966x->ports[i]; + if (!port) + continue; + + if (netif_queue_stopped(port->dev)) + netif_wake_queue(port->dev); + } +} + +static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight) +{ + struct lan966x_tx *tx =3D &lan966x->tx; + struct lan966x_tx_dcb_buf *dcb_buf; + struct lan966x_db *db; + unsigned long flags; + bool clear =3D false; + int i; + + spin_lock_irqsave(&lan966x->tx_lock, flags); + for (i =3D 0; i < FDMA_DCB_MAX; ++i) { + dcb_buf =3D &tx->dcbs_buf[i]; + + if (!dcb_buf->used) + continue; + + db =3D &tx->dcbs[i].db[0]; + if (!(db->status & FDMA_DCB_STATUS_DONE)) + continue; + + dcb_buf->dev->stats.tx_packets++; + dcb_buf->dev->stats.tx_bytes +=3D dcb_buf->skb->len; + + dcb_buf->used =3D false; + dma_unmap_single(lan966x->dev, + dcb_buf->dma_addr, + dcb_buf->skb->len, + DMA_TO_DEVICE); + if (!dcb_buf->ptp) + dev_kfree_skb_any(dcb_buf->skb); + + clear =3D true; + } + + if (clear) + lan966x_fdma_wakeup_netdev(lan966x); + + spin_unlock_irqrestore(&lan966x->tx_lock, flags); +} + +static bool lan966x_fdma_rx_more_frames(struct lan966x_rx *rx) +{ + struct lan966x_db *db; + + /* Check if there is any data */ + db =3D &rx->dcbs[rx->dcb_index].db[rx->db_index]; + if (unlikely(!(db->status & FDMA_DCB_STATUS_DONE))) + return false; + + return true; +} + +static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx) +{ + struct lan966x *lan966x =3D rx->lan966x; + u64 src_port, timestamp; + struct lan966x_db *db; + struct sk_buff *skb; + struct page *page; + + /* Get the received frame and unmap it */ + db =3D &rx->dcbs[rx->dcb_index].db[rx->db_index]; + page =3D rx->page[rx->dcb_index][rx->db_index]; + skb =3D build_skb(page_address(page), PAGE_SIZE << rx->page_order); + if (unlikely(!skb)) + goto unmap_page; + + dma_unmap_single(lan966x->dev, (dma_addr_t)db->dataptr, + FDMA_DCB_STATUS_BLOCKL(db->status), + DMA_FROM_DEVICE); + skb_put(skb, FDMA_DCB_STATUS_BLOCKL(db->status)); + + lan966x_ifh_get_src_port(skb->data, &src_port); + lan966x_ifh_get_timestamp(skb->data, ×tamp); + + WARN_ON(src_port >=3D lan966x->num_phys_ports); + + skb->dev =3D lan966x->ports[src_port]->dev; + skb_pull(skb, IFH_LEN * sizeof(u32)); + + if (likely(!(skb->dev->features & NETIF_F_RXFCS))) + skb_trim(skb, skb->len - ETH_FCS_LEN); + + lan966x_ptp_rxtstamp(lan966x, skb, timestamp); + skb->protocol =3D eth_type_trans(skb, skb->dev); + + if (lan966x->bridge_mask & BIT(src_port)) { + skb->offload_fwd_mark =3D 1; + + skb_reset_network_header(skb); + if (!lan966x_hw_offload(lan966x, src_port, skb)) + skb->offload_fwd_mark =3D 0; + } + + skb->dev->stats.rx_bytes +=3D skb->len; + skb->dev->stats.rx_packets++; + + return skb; + +unmap_page: + dma_unmap_page(lan966x->dev, (dma_addr_t)db->dataptr, + FDMA_DCB_STATUS_BLOCKL(db->status), + DMA_FROM_DEVICE); + __free_pages(page, rx->page_order); + + return NULL; +} + +static int lan966x_fdma_napi_poll(struct napi_struct *napi, int weight) +{ + struct lan966x *lan966x =3D container_of(napi, struct lan966x, napi); + struct lan966x_rx *rx =3D &lan966x->rx; + int dcb_reload =3D rx->dcb_index; + struct lan966x_rx_dcb *old_dcb; + struct lan966x_db *db; + struct sk_buff *skb; + struct page *page; + int counter =3D 0; + u64 nextptr; + + lan966x_fdma_tx_clear_buf(lan966x, weight); + + /* Get all received skb */ + while (counter < weight) { + if (!lan966x_fdma_rx_more_frames(rx)) + break; + + skb =3D lan966x_fdma_rx_get_frame(rx); + + rx->page[rx->dcb_index][rx->db_index] =3D NULL; + rx->dcb_index++; + rx->dcb_index &=3D FDMA_DCB_MAX - 1; + + if (!skb) + break; + + napi_gro_receive(&lan966x->napi, skb); + counter++; + } + + /* Allocate new pages and map them */ + while (dcb_reload !=3D rx->dcb_index) { + db =3D &rx->dcbs[dcb_reload].db[rx->db_index]; + page =3D lan966x_fdma_rx_alloc_page(rx, db); + if (unlikely(!page)) + break; + rx->page[dcb_reload][rx->db_index] =3D page; + + old_dcb =3D &rx->dcbs[dcb_reload]; + dcb_reload++; + dcb_reload &=3D FDMA_DCB_MAX - 1; + + nextptr =3D rx->dma + ((unsigned long)old_dcb - + (unsigned long)rx->dcbs); + lan966x_fdma_rx_add_dcb(rx, old_dcb, nextptr); + lan966x_fdma_rx_reload(rx); + } + + if (counter < weight && napi_complete_done(napi, counter)) + lan_wr(0xff, lan966x, FDMA_INTR_DB_ENA); + + return counter; +} + +irqreturn_t lan966x_fdma_irq_handler(int irq, void *args) +{ + struct lan966x *lan966x =3D args; + u32 db, err, err_type; + + db =3D lan_rd(lan966x, FDMA_INTR_DB); + err =3D lan_rd(lan966x, FDMA_INTR_ERR); + + if (db) { + lan_wr(0, lan966x, FDMA_INTR_DB_ENA); + lan_wr(db, lan966x, FDMA_INTR_DB); + + napi_schedule(&lan966x->napi); + } + + if (err) { + err_type =3D lan_rd(lan966x, FDMA_ERRORS); + + WARN(1, "Unexpected error: %d, error_type: %d\n", err, err_type); + + lan_wr(err, lan966x, FDMA_INTR_ERR); + lan_wr(err_type, lan966x, FDMA_ERRORS); + } + + return IRQ_HANDLED; +} + +static int lan966x_fdma_get_next_dcb(struct lan966x_tx *tx) +{ + struct lan966x_tx_dcb_buf *dcb_buf; + int i; + + for (i =3D 0; i < FDMA_DCB_MAX; ++i) { + dcb_buf =3D &tx->dcbs_buf[i]; + if (!dcb_buf->used && i !=3D tx->last_in_use) + return i; + } + + return -1; +} + +int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device = *dev) +{ + struct lan966x_port *port =3D netdev_priv(dev); + struct lan966x *lan966x =3D port->lan966x; + struct lan966x_tx_dcb_buf *next_dcb_buf; + struct lan966x_tx_dcb *next_dcb, *dcb; + struct lan966x_tx *tx =3D &lan966x->tx; + struct lan966x_db *next_db; + int needed_headroom; + int needed_tailroom; + dma_addr_t dma_addr; + int next_to_use; + int err; + + /* Get next index */ + next_to_use =3D lan966x_fdma_get_next_dcb(tx); + if (next_to_use < 0) { + netif_stop_queue(dev); + return NETDEV_TX_BUSY; + } + + if (skb_put_padto(skb, ETH_ZLEN)) { + dev->stats.tx_dropped++; + return NETDEV_TX_OK; + } + + /* skb processing */ + needed_headroom =3D max_t(int, IFH_LEN * sizeof(u32) - skb_headroom(skb),= 0); + needed_tailroom =3D max_t(int, ETH_FCS_LEN - skb_tailroom(skb), 0); + if (needed_headroom || needed_tailroom || skb_header_cloned(skb)) { + err =3D pskb_expand_head(skb, needed_headroom, needed_tailroom, + GFP_ATOMIC); + if (unlikely(err)) { + dev->stats.tx_dropped++; + err =3D NETDEV_TX_OK; + goto release; + } + } + + skb_tx_timestamp(skb); + skb_push(skb, IFH_LEN * sizeof(u32)); + memcpy(skb->data, ifh, IFH_LEN * sizeof(u32)); + skb_put(skb, 4); + + dma_addr =3D dma_map_single(lan966x->dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(lan966x->dev, dma_addr)) { + dev->stats.tx_dropped++; + err =3D NETDEV_TX_OK; + goto release; + } + + /* Setup next dcb */ + next_dcb =3D &tx->dcbs[next_to_use]; + next_dcb->nextptr =3D FDMA_DCB_INVALID_DATA; + + next_db =3D &next_dcb->db[0]; + next_db->dataptr =3D dma_addr; + next_db->status =3D FDMA_DCB_STATUS_SOF | + FDMA_DCB_STATUS_EOF | + FDMA_DCB_STATUS_INTR | + FDMA_DCB_STATUS_BLOCKO(0) | + FDMA_DCB_STATUS_BLOCKL(skb->len); + + /* Fill up the buffer */ + next_dcb_buf =3D &tx->dcbs_buf[next_to_use]; + next_dcb_buf->skb =3D skb; + next_dcb_buf->dma_addr =3D dma_addr; + next_dcb_buf->used =3D true; + next_dcb_buf->ptp =3D false; + next_dcb_buf->dev =3D dev; + + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && + LAN966X_SKB_CB(skb)->rew_op =3D=3D IFH_REW_OP_TWO_STEP_PTP) + next_dcb_buf->ptp =3D true; + + if (likely(lan966x->tx.activated)) { + /* Connect current dcb to the next db */ + dcb =3D &tx->dcbs[tx->last_in_use]; + dcb->nextptr =3D tx->dma + (next_to_use * + sizeof(struct lan966x_tx_dcb)); + + lan966x_fdma_tx_reload(tx); + } else { + /* Because it is first time, then just activate */ + lan966x->tx.activated =3D true; + lan966x_fdma_tx_activate(tx); + } + + /* Move to next dcb because this last in use */ + tx->last_in_use =3D next_to_use; + + return NETDEV_TX_OK; + +release: + if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && + LAN966X_SKB_CB(skb)->rew_op =3D=3D IFH_REW_OP_TWO_STEP_PTP) + lan966x_ptp_txtstamp_release(port, skb); + + dev_kfree_skb_any(skb); + return err; +} + +void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *= dev) +{ + if (lan966x->fdma_ndev) + return; + + lan966x->fdma_ndev =3D dev; + netif_napi_add(dev, &lan966x->napi, lan966x_fdma_napi_poll, + NAPI_POLL_WEIGHT); + napi_enable(&lan966x->napi); +} + +void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device= *dev) +{ + if (lan966x->fdma_ndev =3D=3D dev) { + netif_napi_del(&lan966x->napi); + lan966x->fdma_ndev =3D NULL; + } +} + +int lan966x_fdma_init(struct lan966x *lan966x) +{ + int err; + + if (!lan966x->fdma) + return 0; + + lan966x->rx.lan966x =3D lan966x; + lan966x->rx.channel_id =3D FDMA_XTR_CHANNEL; + lan966x->tx.lan966x =3D lan966x; + lan966x->tx.channel_id =3D FDMA_INJ_CHANNEL; + lan966x->tx.last_in_use =3D -1; + + err =3D lan966x_fdma_rx_alloc(&lan966x->rx); + if (err) + return err; + + err =3D lan966x_fdma_tx_alloc(&lan966x->tx); + if (err) { + lan966x_fdma_rx_free(&lan966x->rx); + return err; + } + + lan966x_fdma_rx_start(&lan966x->rx); + + return 0; +} + +void lan966x_fdma_deinit(struct lan966x *lan966x) +{ + if (!lan966x->fdma) + return; + + lan966x_fdma_rx_disable(&lan966x->rx); + lan966x_fdma_tx_disable(&lan966x->tx); + + napi_synchronize(&lan966x->napi); + napi_disable(&lan966x->napi); + + lan966x_fdma_rx_free_pages(&lan966x->rx); + lan966x_fdma_rx_free(&lan966x->rx); + lan966x_fdma_tx_free(&lan966x->tx); +} diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.c index 03f0d149a80b..5424ea869985 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -341,7 +341,10 @@ static int lan966x_port_xmit(struct sk_buff *skb, stru= ct net_device *dev) } =20 spin_lock(&lan966x->tx_lock); - err =3D lan966x_port_ifh_xmit(skb, ifh, dev); + if (port->lan966x->fdma) + err =3D lan966x_fdma_xmit(skb, ifh, dev); + else + err =3D lan966x_port_ifh_xmit(skb, ifh, dev); spin_unlock(&lan966x->tx_lock); =20 return err; @@ -643,6 +646,9 @@ static void lan966x_cleanup_ports(struct lan966x *lan96= 6x) if (port->dev) unregister_netdev(port->dev); =20 + if (lan966x->fdma && lan966x->fdma_ndev =3D=3D port->dev) + lan966x_fdma_netdev_deinit(lan966x, port->dev); + if (port->phylink) { rtnl_lock(); lan966x_port_stop(port->dev); @@ -662,6 +668,9 @@ static void lan966x_cleanup_ports(struct lan966x *lan96= 6x) disable_irq(lan966x->ana_irq); lan966x->ana_irq =3D -ENXIO; } + + if (lan966x->fdma) + devm_free_irq(lan966x->dev, lan966x->fdma_irq, lan966x); } =20 static int lan966x_probe_port(struct lan966x *lan966x, u32 p, @@ -790,12 +799,12 @@ static void lan966x_init(struct lan966x *lan966x) /* Do byte-swap and expect status after last data word * Extraction: Mode: manual extraction) | Byte_swap */ - lan_wr(QS_XTR_GRP_CFG_MODE_SET(1) | + lan_wr(QS_XTR_GRP_CFG_MODE_SET(lan966x->fdma ? 2 : 1) | QS_XTR_GRP_CFG_BYTE_SWAP_SET(1), lan966x, QS_XTR_GRP_CFG(0)); =20 /* Injection: Mode: manual injection | Byte_swap */ - lan_wr(QS_INJ_GRP_CFG_MODE_SET(1) | + lan_wr(QS_INJ_GRP_CFG_MODE_SET(lan966x->fdma ? 2 : 1) | QS_INJ_GRP_CFG_BYTE_SWAP_SET(1), lan966x, QS_INJ_GRP_CFG(0)); =20 @@ -1017,6 +1026,17 @@ static int lan966x_probe(struct platform_device *pde= v) lan966x->ptp =3D 1; } =20 + lan966x->fdma_irq =3D platform_get_irq_byname(pdev, "fdma"); + if (lan966x->fdma_irq > 0) { + err =3D devm_request_irq(&pdev->dev, lan966x->fdma_irq, + lan966x_fdma_irq_handler, 0, + "fdma irq", lan966x); + if (err) + return dev_err_probe(&pdev->dev, err, "Unable to use fdma irq"); + + lan966x->fdma =3D true; + } + /* init switch */ lan966x_init(lan966x); lan966x_stats_init(lan966x); @@ -1055,8 +1075,15 @@ static int lan966x_probe(struct platform_device *pde= v) if (err) goto cleanup_fdb; =20 + err =3D lan966x_fdma_init(lan966x); + if (err) + goto cleanup_ptp; + return 0; =20 +cleanup_ptp: + lan966x_ptp_deinit(lan966x); + cleanup_fdb: lan966x_fdb_deinit(lan966x); =20 @@ -1076,6 +1103,7 @@ static int lan966x_remove(struct platform_device *pde= v) { struct lan966x *lan966x =3D platform_get_drvdata(pdev); =20 + lan966x_fdma_deinit(lan966x); lan966x_cleanup_ports(lan966x); =20 cancel_delayed_work_sync(&lan966x->stats_work); diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.h index b692c612f235..1ab20b6ec278 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -61,6 +61,22 @@ #define IFH_REW_OP_ONE_STEP_PTP 0x3 #define IFH_REW_OP_TWO_STEP_PTP 0x4 =20 +#define FDMA_RX_DCB_MAX_DBS 1 +#define FDMA_TX_DCB_MAX_DBS 1 +#define FDMA_DCB_INFO_DATAL(x) ((x) & GENMASK(15, 0)) + +#define FDMA_DCB_STATUS_BLOCKL(x) ((x) & GENMASK(15, 0)) +#define FDMA_DCB_STATUS_SOF BIT(16) +#define FDMA_DCB_STATUS_EOF BIT(17) +#define FDMA_DCB_STATUS_INTR BIT(18) +#define FDMA_DCB_STATUS_DONE BIT(19) +#define FDMA_DCB_STATUS_BLOCKO(x) (((x) << 20) & GENMASK(31, 20)) +#define FDMA_DCB_INVALID_DATA 0x1 + +#define FDMA_XTR_CHANNEL 6 +#define FDMA_INJ_CHANNEL 0 +#define FDMA_DCB_MAX 512 + /* MAC table entry types. * ENTRYTYPE_NORMAL is subject to aging. * ENTRYTYPE_LOCKED is not subject to aging. @@ -76,6 +92,83 @@ enum macaccess_entry_type { =20 struct lan966x_port; =20 +struct lan966x_db { + u64 dataptr; + u64 status; +}; + +struct lan966x_rx_dcb { + u64 nextptr; + u64 info; + struct lan966x_db db[FDMA_RX_DCB_MAX_DBS]; +}; + +struct lan966x_tx_dcb { + u64 nextptr; + u64 info; + struct lan966x_db db[FDMA_TX_DCB_MAX_DBS]; +}; + +struct lan966x_rx { + struct lan966x *lan966x; + + /* Pointer to the array of hardware dcbs. */ + struct lan966x_rx_dcb *dcbs; + + /* Pointer to the last address in the dcbs. */ + struct lan966x_rx_dcb *last_entry; + + /* For each DB, there is a page */ + struct page *page[FDMA_DCB_MAX][FDMA_RX_DCB_MAX_DBS]; + + /* Represents the db_index, it can have a value between 0 and + * FDMA_RX_DCB_MAX_DBS, once it reaches the value of FDMA_RX_DCB_MAX_DBS + * it means that the DCB can be reused. + */ + int db_index; + + /* Represents the index in the dcbs. It has a value between 0 and + * FDMA_DCB_MAX + */ + int dcb_index; + + /* Represents the dma address to the dcbs array */ + dma_addr_t dma; + + /* Represents the page order that is used to allocate the pages for the + * RX buffers. This value is calculated based on max MTU of the devices. + */ + u8 page_order; + + u8 channel_id; +}; + +struct lan966x_tx_dcb_buf { + struct net_device *dev; + struct sk_buff *skb; + dma_addr_t dma_addr; + bool used; + bool ptp; +}; + +struct lan966x_tx { + struct lan966x *lan966x; + + /* Pointer to the dcb list */ + struct lan966x_tx_dcb *dcbs; + u16 last_in_use; + + /* Represents the DMA address to the first entry of the dcb entries. */ + dma_addr_t dma; + + /* Array of dcbs that are given to the HW */ + struct lan966x_tx_dcb_buf *dcbs_buf; + + u8 channel_id; + + bool activated; +}; + struct lan966x_stat_layout { u32 offset; char name[ETH_GSTRING_LEN]; @@ -137,6 +230,7 @@ struct lan966x { int xtr_irq; int ana_irq; int ptp_irq; + int fdma_irq; =20 /* worqueue for fdb */ struct workqueue_struct *fdb_work; @@ -153,6 +247,13 @@ struct lan966x { spinlock_t ptp_ts_id_lock; /* lock for ts_id */ struct mutex ptp_lock; /* lock for ptp interface state */ u16 ptp_skbs; + + /* fdma */ + bool fdma; + struct net_device *fdma_ndev; + struct lan966x_rx rx; + struct lan966x_tx tx; + struct napi_struct napi; }; =20 struct lan966x_port_config { @@ -292,6 +393,13 @@ void lan966x_ptp_txtstamp_release(struct lan966x_port = *port, struct sk_buff *skb); irqreturn_t lan966x_ptp_irq_handler(int irq, void *args); =20 +int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device = *dev); +void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *= dev); +void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device= *dev); +int lan966x_fdma_init(struct lan966x *lan966x); +void lan966x_fdma_deinit(struct lan966x *lan966x); +irqreturn_t lan966x_fdma_irq_handler(int irq, void *args); + static inline void __iomem *lan_addr(void __iomem *base[], int id, int tinst, int tcnt, int gbase, int ginst, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_port.c index 237555845a52..f141644e4372 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c @@ -393,6 +393,9 @@ void lan966x_port_init(struct lan966x_port *port) =20 lan966x_port_config_down(port); =20 + if (lan966x->fdma) + lan966x_fdma_netdev_init(lan966x, port->dev); + if (config->portmode !=3D PHY_INTERFACE_MODE_QSGMII) return; =20 --=20 2.33.0 From nobody Mon May 11 12:11:17 2026 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4FE0CC433EF for ; Fri, 8 Apr 2022 07:01:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229719AbiDHHD3 (ORCPT ); Fri, 8 Apr 2022 03:03:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47986 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229631AbiDHHDH (ORCPT ); Fri, 8 Apr 2022 03:03:07 -0400 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.154.123]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CE53E9D078; Fri, 8 Apr 2022 00:01:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1649401264; x=1680937264; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=51czlh0dwlk2nEU51JbbRM3A1HF2vk3dTXhINtaCj0s=; b=nHhhqTH36l8zTRyGnMOr/stox+2iglLKs4cHNdW4ySvzT0UVkivJiSAY XAZtu0awWuny5GNblM3CaIGh6e7fYrmh9RirpNfI5OsaXcHNIREWlBRme er+vYP4UIQEqUNDubDvPUGzQGupDUuRtX8GG+S4DgSIj6s6xYf3ylEPXQ kXHB7MIBuiXmF5qVNPffD1+4wcnVNjixBTfFjBPFuKHj5AWL8obQtPt+8 FUcLoTYNCVXfNJvpyt9D/uk9iRdM4e8XFXFVcWKvAlxgifR7Fvc2Ch6x9 YEGLpYCQq7fZu8NC/KrrcDEau6c7PiW/jGNfn3KjQfT/QqeWN2saivvIE A==; X-IronPort-AV: E=Sophos;i="5.90,244,1643698800"; d="scan'208";a="91729011" Received: from smtpout.microchip.com (HELO email.microchip.com) ([198.175.253.82]) by esa6.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 08 Apr 2022 00:01:03 -0700 Received: from chn-vm-ex01.mchp-main.com (10.10.85.143) by chn-vm-ex04.mchp-main.com (10.10.85.152) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.17; Fri, 8 Apr 2022 00:01:03 -0700 Received: from soft-dev3-1.microsemi.net (10.10.115.15) by chn-vm-ex01.mchp-main.com (10.10.85.143) with Microsoft SMTP Server id 15.1.2375.17 via Frontend Transport; Fri, 8 Apr 2022 00:01:01 -0700 From: Horatiu Vultur To: , CC: , , , , , Horatiu Vultur Subject: [PATCH net-next v4 4/4] net: lan966x: Update FDMA to change MTU. Date: Fri, 8 Apr 2022 09:03:57 +0200 Message-ID: <20220408070357.559899-5-horatiu.vultur@microchip.com> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20220408070357.559899-1-horatiu.vultur@microchip.com> References: <20220408070357.559899-1-horatiu.vultur@microchip.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" When changing the MTU, it is required to change also the size of the DBs. In case those frames will arrive to CPU. Signed-off-by: Horatiu Vultur Tested-by: Michael Walle # on kontron-kswitch-d10 --- .../ethernet/microchip/lan966x/lan966x_fdma.c | 134 ++++++++++++++++++ .../ethernet/microchip/lan966x/lan966x_main.c | 14 +- .../ethernet/microchip/lan966x/lan966x_main.h | 1 + 3 files changed, 148 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_fdma.c index f5fdb7455a41..9e2a7323eaf0 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c @@ -336,6 +336,20 @@ static void lan966x_fdma_wakeup_netdev(struct lan966x = *lan966x) } } =20 +static void lan966x_fdma_stop_netdev(struct lan966x *lan966x) +{ + struct lan966x_port *port; + int i; + + for (i =3D 0; i < lan966x->num_phys_ports; ++i) { + port =3D lan966x->ports[i]; + if (!port) + continue; + + netif_stop_queue(port->dev); + } +} + static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight) { struct lan966x_tx *tx =3D &lan966x->tx; @@ -644,6 +658,126 @@ int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *if= h, struct net_device *dev) return err; } =20 +static int lan966x_fdma_get_max_mtu(struct lan966x *lan966x) +{ + int max_mtu =3D 0; + int i; + + for (i =3D 0; i < lan966x->num_phys_ports; ++i) { + int mtu; + + if (!lan966x->ports[i]) + continue; + + mtu =3D lan966x->ports[i]->dev->mtu; + if (mtu > max_mtu) + max_mtu =3D mtu; + } + + return max_mtu; +} + +static int lan966x_qsys_sw_status(struct lan966x *lan966x) +{ + return lan_rd(lan966x, QSYS_SW_STATUS(CPU_PORT)); +} + +static int lan966x_fdma_reload(struct lan966x *lan966x, int new_mtu) +{ + void *rx_dcbs, *tx_dcbs, *tx_dcbs_buf; + dma_addr_t rx_dma, tx_dma; + u32 size; + int err; + + /* Store these for later to free them */ + rx_dma =3D lan966x->rx.dma; + tx_dma =3D lan966x->tx.dma; + rx_dcbs =3D lan966x->rx.dcbs; + tx_dcbs =3D lan966x->tx.dcbs; + tx_dcbs_buf =3D lan966x->tx.dcbs_buf; + + napi_synchronize(&lan966x->napi); + napi_disable(&lan966x->napi); + lan966x_fdma_stop_netdev(lan966x); + + lan966x_fdma_rx_disable(&lan966x->rx); + lan966x_fdma_rx_free_pages(&lan966x->rx); + lan966x->rx.page_order =3D round_up(new_mtu, PAGE_SIZE) / PAGE_SIZE - 1; + err =3D lan966x_fdma_rx_alloc(&lan966x->rx); + if (err) + goto restore; + lan966x_fdma_rx_start(&lan966x->rx); + + size =3D sizeof(struct lan966x_rx_dcb) * FDMA_DCB_MAX; + size =3D ALIGN(size, PAGE_SIZE); + dma_free_coherent(lan966x->dev, size, rx_dcbs, rx_dma); + + lan966x_fdma_tx_disable(&lan966x->tx); + err =3D lan966x_fdma_tx_alloc(&lan966x->tx); + if (err) + goto restore_tx; + + size =3D sizeof(struct lan966x_tx_dcb) * FDMA_DCB_MAX; + size =3D ALIGN(size, PAGE_SIZE); + dma_free_coherent(lan966x->dev, size, tx_dcbs, tx_dma); + + kfree(tx_dcbs_buf); + + lan966x_fdma_wakeup_netdev(lan966x); + napi_enable(&lan966x->napi); + + return err; +restore: + lan966x->rx.dma =3D rx_dma; + lan966x->tx.dma =3D tx_dma; + lan966x_fdma_rx_start(&lan966x->rx); + +restore_tx: + lan966x->rx.dcbs =3D rx_dcbs; + lan966x->tx.dcbs =3D tx_dcbs; + lan966x->tx.dcbs_buf =3D tx_dcbs_buf; + + return err; +} + +int lan966x_fdma_change_mtu(struct lan966x *lan966x) +{ + int max_mtu; + int err; + u32 val; + + max_mtu =3D lan966x_fdma_get_max_mtu(lan966x); + max_mtu +=3D IFH_LEN * sizeof(u32); + + if (round_up(max_mtu, PAGE_SIZE) / PAGE_SIZE - 1 =3D=3D + lan966x->rx.page_order) + return 0; + + /* Disable the CPU port */ + lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(0), + QSYS_SW_PORT_MODE_PORT_ENA, + lan966x, QSYS_SW_PORT_MODE(CPU_PORT)); + + /* Flush the CPU queues */ + readx_poll_timeout(lan966x_qsys_sw_status, lan966x, + val, !(QSYS_SW_STATUS_EQ_AVAIL_GET(val)), + READL_SLEEP_US, READL_TIMEOUT_US); + + /* Add a sleep in case there are frames between the queues and the CPU + * port + */ + usleep_range(1000, 2000); + + err =3D lan966x_fdma_reload(lan966x, max_mtu); + + /* Enable back the CPU port */ + lan_rmw(QSYS_SW_PORT_MODE_PORT_ENA_SET(1), + QSYS_SW_PORT_MODE_PORT_ENA, + lan966x, QSYS_SW_PORT_MODE(CPU_PORT)); + + return err; +} + void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *= dev) { if (lan966x->fdma_ndev) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.c index 5424ea869985..8467ffbdafa9 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -354,12 +354,24 @@ static int lan966x_port_change_mtu(struct net_device = *dev, int new_mtu) { struct lan966x_port *port =3D netdev_priv(dev); struct lan966x *lan966x =3D port->lan966x; + int old_mtu =3D dev->mtu; + int err; =20 lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu), lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); dev->mtu =3D new_mtu; =20 - return 0; + if (!lan966x->fdma) + return 0; + + err =3D lan966x_fdma_change_mtu(lan966x); + if (err) { + lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(old_mtu), + lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port)); + dev->mtu =3D old_mtu; + } + + return err; } =20 static int lan966x_mc_unsync(struct net_device *dev, const unsigned char *= addr) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/driver= s/net/ethernet/microchip/lan966x/lan966x_main.h index 1ab20b6ec278..5213263c4e87 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h @@ -394,6 +394,7 @@ void lan966x_ptp_txtstamp_release(struct lan966x_port *= port, irqreturn_t lan966x_ptp_irq_handler(int irq, void *args); =20 int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device = *dev); +int lan966x_fdma_change_mtu(struct lan966x *lan966x); void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *= dev); void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device= *dev); int lan966x_fdma_init(struct lan966x *lan966x); --=20 2.33.0