From nobody Tue Sep 29 07:01:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0417B3603F8; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786448757; cv=none; b=QFiiPLni40ZIFaNIpdKv/yNY0sUS42HmWCMG+4WJ+QbmzjC6N7RpGRF/aaoohsMIaIefSP4wnQA+8YG7DVjXNXTkFynpbeaj71I14Prmo+RRm+cdCx5P2H/f1rOhFZx/8s4dl8LJazM1nYLq4X8zsF7TysuP0xLJcdtzBPS3Dho= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786448757; c=relaxed/simple; bh=une3Jz7mmYJxLNfmJT5dY1vwBR13DWmia6kGVSZevmM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oJx8Vz5CYE19909I8C/eVjufBiIpanSNjwJiCSfGxYIE/gb+l7udJhrgVvZgiY5Il/R4fyUMgU8FhyNs0ttku1E+Mi3W32x6N/0w5OFvW7yXa377eeYfvgdEQCkNFDG7lTCtpyaLlU2ifu7QOKXskqd0QnFqSwOIwFhlcMqFqpk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DuFIo6Uz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DuFIo6Uz" Received: by smtp.kernel.org (Postfix) with ESMTPS id 9A7FFC2BCF6; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786448756; bh=une3Jz7mmYJxLNfmJT5dY1vwBR13DWmia6kGVSZevmM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=DuFIo6UzZTPXIsmy4k25Nnf+NwIU1Ny56c4oH23/w9khzxJ+Z+owGgaKXTRWY+89c Xc5/MG5lNeoDci26iV6bTXwjdaeoFfSK1u/vFwLYyQY/7cJaxWoXtpaeR4EDT/iIVJ 7k4IrqQ+Vi9RN2L/sbo4ha08ZiN5jsGEQH3aUjxk4pAc7uItcAharfVHlgAN1EpehF Eu1l9+2RLm9FAbyGn0UPgojkLLxctfjMEgMiaLtne2miC4WppEUy44Yg8KrkaLjqU0 kcNJPxe20VqgYvzb6Z9ox/mSPi+7mX1uGlkBHfkMcmKB9vZS3x4Zd/fjdXD5SRPQsD LAecZrj3APyFA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 78B69C5B56A; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) From: Cedric Jehasse via B4 Relay Date: Tue, 11 Aug 2026 13:45:47 +0200 Subject: [PATCH net-next v8 1/3] net/sched: cbs: add extack to struct tc_cbs_qopt_offload Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260811-net-next-mv88e6xxx-cbs-v8-1-10d0baab2905@luminex.be> References: <20260811-net-next-mv88e6xxx-cbs-v8-0-10d0baab2905@luminex.be> In-Reply-To: <20260811-net-next-mv88e6xxx-cbs-v8-0-10d0baab2905@luminex.be> To: Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Jamal Hadi Salim , Jiri Pirko , Vinicius Costa Gomes Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Luke Howard , =?utf-8?q?Marek_Beh=C3=BAn?= , Cedric Jehasse , Cedric Jehasse X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786448754; l=1288; i=cedric.jehasse@luminex.be; s=20260213; h=from:subject:message-id; bh=aNoIWhFNHrFQcCZfGOBB7BByzBoikUxu5dgW0xHObus=; b=eYcjP2tH+oPltczi2zPEVpvlrxZi/b8CgfAogNIgpdatuzALLD0WbWedHb6jOGXVpbqfJGUVu 6mW+tPhQHM2BcZLq2xEmw7eudDCM5o27KlNkVJa09M0qjQ4Waiow9jA X-Developer-Key: i=cedric.jehasse@luminex.be; a=ed25519; pk=DL2RaHc2bc7tTDTMJdugm42BtJk4Ip+7V41Gkj+Avjk= X-Endpoint-Received: by B4 Relay for cedric.jehasse@luminex.be/20260213 with auth_id=638 X-Original-From: Cedric Jehasse Reply-To: cedric.jehasse@luminex.be From: Cedric Jehasse To be able to report reason for rejection when cbs offloading fails. Signed-off-by: Cedric Jehasse --- include/net/pkt_sched.h | 1 + net/sched/sch_cbs.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index 18a419cd9d949..d35c87004c279 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -150,6 +150,7 @@ struct tc_cbs_qopt_offload { s32 locredit; s32 idleslope; s32 sendslope; + struct netlink_ext_ack *extack; }; =20 struct tc_etf_qopt_offload { diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c index 1c93469c56e3d..87c2eda108c8c 100644 --- a/net/sched/sch_cbs.c +++ b/net/sched/sch_cbs.c @@ -307,10 +307,12 @@ static int cbs_enable_offload(struct net_device *dev,= struct cbs_sched_data *q, cbs.locredit =3D opt->locredit; cbs.idleslope =3D opt->idleslope; cbs.sendslope =3D opt->sendslope; + cbs.extack =3D extack; =20 err =3D ops->ndo_setup_tc(dev, TC_SETUP_QDISC_CBS, &cbs); if (err < 0) { - NL_SET_ERR_MSG(extack, "Specified device failed to setup cbs hardware of= fload"); + NL_SET_ERR_MSG_WEAK(extack, + "Specified device failed to setup cbs hardware offload"); return err; } =20 --=20 2.43.0 From nobody Tue Sep 29 07:01:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04212368D45; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786448757; cv=none; b=PK7jKfI3GUJDGIgYZossRt/H/YT+X5g0Iy1lXDfUvnKx2D6ygktKmxCA+6ydRjJTTvJMuPc2xy/8oj5ynSuQKAHkYbxM+F+1+NHn1jqF/8pt9UJdURJ2ahD76Kqbf94AYLNUn5HMjigms1iEFQVKLKrPMcl/JyOrgB6ul3KZ8GU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786448757; c=relaxed/simple; bh=bL+dw7nZ4smpe5+bHljStvN1ejOmLM/lXKfbhLG7gMo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=EPIaFp+QrV75wxc1K1UilyGBvCfurDQING+md/LK5lbe9hrAaAh0m18IknCT9rAF/GwNnQtzzihSIAmxsHWQ5N1yy7axn8uVDFosmOB2rxHtqqcGOUChoaqeBM1yKH8Zy2yCXLqOfu5qFHgtgeksXpjuVJXkjkZIwha/TWxY5Qk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s4MD9SMG; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s4MD9SMG" Received: by smtp.kernel.org (Postfix) with ESMTPS id AA03AC2BCFA; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786448756; bh=bL+dw7nZ4smpe5+bHljStvN1ejOmLM/lXKfbhLG7gMo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=s4MD9SMGqMktRS8kt2K6Q22Fs1wZX4Hy/rURQ6hhjNVNqe1mPGU4sd0N1d6adXkXe uW0i3EpyuWxDSm83JbEnxN3jzQYAj0wVnqn7l3sX18dLhejmN5fhVH/1OwGOV5/c8Q x7JDKtGeDg45EmqyB4DaTumfsYEvSf9Q+adu3chb9pYzJmFY6Q4aT3UrD7q7QA2uy3 e+lLJwe8EaMLLDP5NBqCNeZ6j7KWNHlBHk3QFNzrUyAZngglfIzie/pcy8zvtoty1G 0Jf9uPWqf0npKAgqNYjB6A9SmPTDU9F6PAhe7Q41OgV7zer7QfI1jC6E/0Hl766G0V cIvf9lXbu/FGQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8B122C5CFC1; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) From: Cedric Jehasse via B4 Relay Date: Tue, 11 Aug 2026 13:45:48 +0200 Subject: [PATCH net-next v8 2/3] net: dsa: mv88e6xxx: use the hw tx queues Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260811-net-next-mv88e6xxx-cbs-v8-2-10d0baab2905@luminex.be> References: <20260811-net-next-mv88e6xxx-cbs-v8-0-10d0baab2905@luminex.be> In-Reply-To: <20260811-net-next-mv88e6xxx-cbs-v8-0-10d0baab2905@luminex.be> To: Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Jamal Hadi Salim , Jiri Pirko , Vinicius Costa Gomes Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Luke Howard , =?utf-8?q?Marek_Beh=C3=BAn?= , Cedric Jehasse , Cedric Jehasse X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786448754; l=11508; i=cedric.jehasse@luminex.be; s=20260213; h=from:subject:message-id; bh=+d3GarFIv+8jgYa2BdKPESoxgq5Xh3C5c/F3WWG67NU=; b=udc3HLmCyDMr4KResFzuYujzL8yzPf3vWnbzj9Hu+TUguPoWm4X7LKg1iKYSIwsKHNFAc5h/e HLY0K5L1vdKBPeNNyCdZiuloEX6BNTw8x2UsWHS757pR5CzLDPmiUc5 X-Developer-Key: i=cedric.jehasse@luminex.be; a=ed25519; pk=DL2RaHc2bc7tTDTMJdugm42BtJk4Ip+7V41Gkj+Avjk= X-Endpoint-Received: by B4 Relay for cedric.jehasse@luminex.be/20260213 with auth_id=638 X-Original-From: Cedric Jehasse Reply-To: cedric.jehasse@luminex.be From: Cedric Jehasse When transmitting fill in the PRI field in the dsa tag to select the egress queue is sent to. From the datasheets i've looked at these switches have 4 or 8 transmit queues per port. Note: skbs with skb->offload_fwd_mark set use the DSA_CMD_FORWARD tag. These are processed as normal ingress frames, meaning the queue they end up in can still be altered by other switch config. eg. priority overrides, tcam policies. This isn't done for vlan tagged frames because this would overwrite the PCP value in the vlan tag (The PRI field in the dsa tag is used as the PCP value in the vlan tag). Signed-off-by: Cedric Jehasse --- drivers/net/dsa/mv88e6xxx/chip.c | 35 +++++++++++++++++++++++++++++++++++ drivers/net/dsa/mv88e6xxx/chip.h | 1 + net/dsa/tag_dsa.c | 11 ++++++++++- 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/c= hip.c index 80b877c74513d..47e531f24e5f2 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3990,6 +3990,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) =20 chip->ds =3D ds; ds->user_mii_bus =3D mv88e6xxx_default_mdio_bus(chip); + ds->num_tx_queues =3D chip->info->num_tx_queues; =20 /* Since virtual bridges are mapped in the PVT, the number we support * depends on the physical switch topology. We need to let DSA figure @@ -5706,6 +5707,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { */ .num_ports =3D 7, .num_internal_phys =3D 2, + .num_tx_queues =3D 4, .invalid_port_mask =3D BIT(2) | BIT(3) | BIT(4), .max_vid =3D 4095, .port_base_addr =3D 0x8, @@ -5728,6 +5730,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_databases =3D 64, .num_ports =3D 7, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .port_base_addr =3D 0x08, .phy_base_addr =3D 0x00, @@ -5750,6 +5753,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 10, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5774,6 +5778,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 11, .num_internal_phys =3D 0, + .num_tx_queues =3D 4, .max_vid =3D 4095, .port_base_addr =3D 0x10, .phy_base_addr =3D 0x0, @@ -5795,6 +5800,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 11, .num_internal_phys =3D 8, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5820,6 +5826,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 1024, .num_ports =3D 3, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5845,6 +5852,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 8, .num_internal_phys =3D 0, + .num_tx_queues =3D 4, .max_vid =3D 4095, .port_base_addr =3D 0x10, .phy_base_addr =3D 0x0, @@ -5867,6 +5875,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 6, .num_internal_phys =3D 5, .num_gpio =3D 11, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5892,6 +5901,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 1024, .num_ports =3D 6, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5918,6 +5928,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 6, .num_internal_phys =3D 0, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5943,6 +5954,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 7, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5969,6 +5981,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 7, .num_internal_phys =3D 5, .num_gpio =3D 15, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -5994,6 +6007,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 7, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6020,6 +6034,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 7, .num_internal_phys =3D 5, .num_gpio =3D 15, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6045,6 +6060,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 10, .num_internal_phys =3D 0, + .num_tx_queues =3D 4, .max_vid =3D 4095, .port_base_addr =3D 0x10, .phy_base_addr =3D 0x0, @@ -6068,6 +6084,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .num_gpio =3D 16, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6093,6 +6110,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .num_gpio =3D 16, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6117,6 +6135,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 16384, .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6142,6 +6161,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 8, .internal_phys_offset =3D 1, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6168,6 +6188,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 8, .num_tcam_entries =3D 256, .internal_phys_offset =3D 1, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6198,6 +6219,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 7, .num_internal_phys =3D 2, .invalid_port_mask =3D BIT(2) | BIT(3) | BIT(4), + .num_tx_queues =3D 4, .max_vid =3D 4095, .port_base_addr =3D 0x08, .phy_base_addr =3D 0x00, @@ -6222,6 +6244,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 7, .num_internal_phys =3D 5, .num_gpio =3D 15, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6247,6 +6270,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_databases =3D 64, .num_ports =3D 7, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .port_base_addr =3D 0x08, .phy_base_addr =3D 0x00, @@ -6271,6 +6295,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 9, .num_gpio =3D 16, .num_tcam_entries =3D 256, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6299,6 +6324,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 2, .internal_phys_offset =3D 3, .num_gpio =3D 15, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6327,6 +6353,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 2, .internal_phys_offset =3D 3, .num_gpio =3D 15, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6354,6 +6381,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 5, .num_ports =3D 6, .num_gpio =3D 11, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6380,6 +6408,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 7, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6405,6 +6434,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_macs =3D 8192, .num_ports =3D 7, .num_internal_phys =3D 5, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6431,6 +6461,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 7, .num_internal_phys =3D 5, .num_gpio =3D 15, + .num_tx_queues =3D 4, .max_vid =3D 4095, .max_sid =3D 63, .port_base_addr =3D 0x10, @@ -6459,6 +6490,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .invalid_port_mask =3D BIT(1) | BIT(2) | BIT(8), .num_internal_phys =3D 5, .internal_phys_offset =3D 3, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6485,6 +6517,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_internal_phys =3D 9, .num_gpio =3D 16, .num_tcam_entries =3D 256, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6512,6 +6545,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 9, .num_gpio =3D 16, + .num_tx_queues =3D 8, .max_vid =3D 8191, .max_sid =3D 63, .port_base_addr =3D 0x0, @@ -6538,6 +6572,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .num_ports =3D 11, /* 10 + Z80 */ .num_internal_phys =3D 8, .num_tcam_entries =3D 256, + .num_tx_queues =3D 8, .internal_phys_offset =3D 1, .max_vid =3D 8191, .max_sid =3D 63, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/c= hip.h index f4894bdc21ba8..3a1d79a117dca 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -136,6 +136,7 @@ struct mv88e6xxx_info { unsigned int num_internal_phys; unsigned int num_gpio; unsigned int num_tcam_entries; + unsigned int num_tx_queues; unsigned int max_vid; unsigned int max_sid; unsigned int port_base_addr; diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c index d5ffee35fbb53..2bb71cd343e79 100644 --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -179,8 +179,17 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb= , struct net_device *dev, dsa_header[2] &=3D ~0x10; } } else { + u16 queue =3D skb_get_queue_mapping(skb) & 0x7; u16 vid; =20 + /* The PRI field is 3 bits. According to the documentation the + * 2 highest bits specify the egress queue in From_CPU DSA + * tagged frames. On devices with 8 queues it's possible to + * send to the 8 queues, which means the 3 bits are used. + */ + if (dp->ds->num_tx_queues =3D=3D 4) + queue <<=3D 1; + vid =3D br_dev ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE; =20 skb_push(skb, DSA_HLEN + extra); @@ -191,7 +200,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb,= struct net_device *dev, =20 dsa_header[0] =3D (cmd << 6) | tag_dev; dsa_header[1] =3D tag_port << 3; - dsa_header[2] =3D vid >> 8; + dsa_header[2] =3D (queue << 5) | vid >> 8; dsa_header[3] =3D vid & 0xff; } =20 --=20 2.43.0 From nobody Tue Sep 29 07:01:10 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 040532877DE; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786448757; cv=none; b=nFUHZyc+Px3vVdeK8iYjWMdlAuT6A7TMULXQXbZwz6cb2/RVjP6ahaJTWoIk0Iof4CI65mqtvB5GczzRo92y3fWXjEjmuemeT4dPYiPu4etfT1FIxHwpl4J1EnPav2P9lEoHMYwqSrscR/kOD8UO6aNvPoWyYq72TYXoG9TJV8Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786448757; c=relaxed/simple; bh=YCUMuDdQybGVEQK7Ajo8A/pBRwCs5M8UOy0n8a9tNxs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XZ6Fg6FML7Ft3ZbTJ95e+xy+NjU8WDUEacXwQk0hiK4mxBbgQYp/Jhj1SnTnGZqWIErMPltj2DTpW4xFtkJQneraNSrEri/y3+INtm0R2BcDavCc7fbyCC96/uZ97qetCGiOoQfY2aZM6glPBULunDfTwwedSzQF8TVB0eqDBmw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tJ/wjBDV; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tJ/wjBDV" Received: by smtp.kernel.org (Postfix) with ESMTPS id B9317C2BCFB; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1786448756; bh=YCUMuDdQybGVEQK7Ajo8A/pBRwCs5M8UOy0n8a9tNxs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=tJ/wjBDVqrHE/9rRrvv+ZOm3kkUNXmNy631v9mfuiiVbz1PPZtBy4rL8KYKv77+Bc BqVjurpOSeK8RuSmm8LGB4zLD8MLPSPr9l0MvfAr41EeZAShVzdjQEG+dGDFEtGtVZ jhcJAprveFNTnAZiihGhchjN9gsCOts6sTxO0GTFeRTYw9utHxwM6NHxkZQmUEV9CY e/SwNNPa9Nn+yfIj4ZVNMkZU28P9wYvIz3vZhbMDmv4v9rpaSZ5NJCMjQwMr9Rpi5o f06kIDsJDyyM3VH8iDtvxOPud6rzneQqeTkjFaQodxMWBkS5p1s9gkCjhjPeAw0Qxu YEsYEOWDEvrBQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D0ACC5CFE7; Tue, 11 Aug 2026 11:45:56 +0000 (UTC) From: Cedric Jehasse via B4 Relay Date: Tue, 11 Aug 2026 13:45:49 +0200 Subject: [PATCH net-next v8 3/3] net: dsa: mv88e6xxx: add support for credit based shaper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260811-net-next-mv88e6xxx-cbs-v8-3-10d0baab2905@luminex.be> References: <20260811-net-next-mv88e6xxx-cbs-v8-0-10d0baab2905@luminex.be> In-Reply-To: <20260811-net-next-mv88e6xxx-cbs-v8-0-10d0baab2905@luminex.be> To: Andrew Lunn , Vladimir Oltean , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Russell King , Jamal Hadi Salim , Jiri Pirko , Vinicius Costa Gomes Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Luke Howard , =?utf-8?q?Marek_Beh=C3=BAn?= , Cedric Jehasse , Cedric Jehasse X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1786448754; l=19943; i=cedric.jehasse@luminex.be; s=20260213; h=from:subject:message-id; bh=AB35rvz8+lJVUXeONVQZfpgrp+ITr3Hzw6NZUnOhRIo=; b=GEJuZ+FNxdTy/e6eY+PlIzVAVFdAq0Gti79UODoSPucuCbcOehFvpSfL1erNDzM+olkVoWAVN L0tv/fBr4KqB5DbN7eXUXErjfJ9zG+3njWRLE1yiWvUasJCKne2He+W X-Developer-Key: i=cedric.jehasse@luminex.be; a=ed25519; pk=DL2RaHc2bc7tTDTMJdugm42BtJk4Ip+7V41Gkj+Avjk= X-Endpoint-Received: by B4 Relay for cedric.jehasse@luminex.be/20260213 with auth_id=638 X-Original-From: Cedric Jehasse Reply-To: cedric.jehasse@luminex.be From: Cedric Jehasse Some of the chips supported by this driver have credit based shaper support. Support is added for the 6341, 6352, 6390 and 6393 families. This is configured using the Qav registers in the AVB register block. There are small differences in the Qav registers between the chip families (eg. the unit used for the rate and number of bits in the registers). mv88e6xxx_qav_info is introduced to configure this per chip. Eg. setting up 20mbps credit based shaper on a 1GBit link: tc qdisc add dev p8 parent root handle 100: mqprio \ num_tc 8 \ map 0 0 6 7 0 5 0 0 0 0 0 0 0 0 0 0 \ queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 \ hw 0 tc qdisc replace dev p8 parent 100:8 cbs locredit -1470 hicredit 30 \ sendslope -980000 idleslope 20000 offload 1 Note: only idleslope and hicredit can be programmed in the switch registers, other parameters won't affect settings. Signed-off-by: Cedric Jehasse --- drivers/net/dsa/mv88e6xxx/chip.c | 141 ++++++++++++++++++++++++++++= ++++ drivers/net/dsa/mv88e6xxx/chip.h | 20 +++++ drivers/net/dsa/mv88e6xxx/global2.h | 3 + drivers/net/dsa/mv88e6xxx/global2_avb.c | 21 +++++ drivers/net/dsa/mv88e6xxx/port.c | 63 ++++++++++++++ drivers/net/dsa/mv88e6xxx/port.h | 20 +++++ 6 files changed, 268 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/c= hip.c index 47e531f24e5f2..a567ee9b6ce0d 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -32,6 +32,7 @@ #include #include #include +#include =20 #include "chip.h" #include "devlink.h" @@ -5024,6 +5025,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops =3D { .port_set_ether_type =3D mv88e6351_port_set_ether_type, .port_set_jumbo_size =3D mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting =3D mv88e6097_port_egress_rate_limiting, + .port_set_scheduling_mode =3D mv88e6352_port_set_scheduling_mode, .port_pause_limit =3D mv88e6097_port_pause_limit, .port_disable_learn_limit =3D mv88e6xxx_port_disable_learn_limit, .port_disable_pri_override =3D mv88e6xxx_port_disable_pri_override, @@ -5307,6 +5309,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops =3D { .port_set_ether_type =3D mv88e6351_port_set_ether_type, .port_set_jumbo_size =3D mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting =3D mv88e6097_port_egress_rate_limiting, + .port_set_scheduling_mode =3D mv88e6352_port_set_scheduling_mode, .port_pause_limit =3D mv88e6097_port_pause_limit, .port_disable_learn_limit =3D mv88e6xxx_port_disable_learn_limit, .port_disable_pri_override =3D mv88e6xxx_port_disable_pri_override, @@ -5465,6 +5468,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops =3D { .port_set_ether_type =3D mv88e6351_port_set_ether_type, .port_set_jumbo_size =3D mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting =3D mv88e6097_port_egress_rate_limiting, + .port_set_scheduling_mode =3D mv88e6352_port_set_scheduling_mode, .port_pause_limit =3D mv88e6097_port_pause_limit, .port_disable_learn_limit =3D mv88e6xxx_port_disable_learn_limit, .port_disable_pri_override =3D mv88e6xxx_port_disable_pri_override, @@ -5534,6 +5538,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops =3D { .port_get_cmode =3D mv88e6352_port_get_cmode, .port_set_cmode =3D mv88e6390_port_set_cmode, .port_setup_message_port =3D mv88e6xxx_setup_message_port, + .port_set_scheduling_mode =3D mv88e6390_port_set_scheduling_mode, .stats_snapshot =3D mv88e6390_g1_stats_snapshot, .stats_set_histogram =3D mv88e6390_g1_stats_set_histogram, .stats_get_sset_count =3D mv88e6320_stats_get_sset_count, @@ -5598,6 +5603,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops =3D { .port_get_cmode =3D mv88e6352_port_get_cmode, .port_set_cmode =3D mv88e6390x_port_set_cmode, .port_setup_message_port =3D mv88e6xxx_setup_message_port, + .port_set_scheduling_mode =3D mv88e6390_port_set_scheduling_mode, .stats_snapshot =3D mv88e6390_g1_stats_snapshot, .stats_set_histogram =3D mv88e6390_g1_stats_set_histogram, .stats_get_sset_count =3D mv88e6320_stats_get_sset_count, @@ -5654,6 +5660,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops =3D { .port_set_ether_type =3D mv88e6393x_port_set_ether_type, .port_set_jumbo_size =3D mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting =3D mv88e6097_port_egress_rate_limiting, + .port_set_scheduling_mode =3D mv88e6390_port_set_scheduling_mode, .port_pause_limit =3D mv88e6390_port_pause_limit, .port_disable_learn_limit =3D mv88e6xxx_port_disable_learn_limit, .port_disable_pri_override =3D mv88e6xxx_port_disable_pri_override, @@ -5696,6 +5703,27 @@ static const struct mv88e6xxx_ops mv88e6393x_ops =3D= { .tcam_ops =3D &mv88e6393_tcam_ops, }; =20 +static const struct mv88e6xxx_qav_info mv88e6352_qav_info =3D { + .rate_unit =3D 32, + .rate_mask =3D GENMASK(14, 0), + .hilimit_mask =3D GENMASK(14, 0), + .queue_mask =3D GENMASK(3, 0), +}; + +static const struct mv88e6xxx_qav_info mv88e6341_qav_info =3D { + .rate_unit =3D 64, + .rate_mask =3D GENMASK(15, 0), + .hilimit_mask =3D GENMASK(13, 0), + .queue_mask =3D GENMASK(3, 0), +}; + +static const struct mv88e6xxx_qav_info mv88e6390_qav_info =3D { + .rate_unit =3D 64, + .rate_mask =3D GENMASK(15, 0), + .hilimit_mask =3D GENMASK(13, 0), + .queue_mask =3D GENMASK(7, 0), +}; + static const struct mv88e6xxx_info mv88e6xxx_table[] =3D { [MV88E6020] =3D { .prod_num =3D MV88E6XXX_PORT_SWITCH_ID_PROD_6020, @@ -6260,6 +6288,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .multi_chip =3D true, .edsa_support =3D MV88E6XXX_EDSA_SUPPORTED, .ptp_support =3D true, + .qav =3D &mv88e6352_qav_info, .ops =3D &mv88e6240_ops, }, =20 @@ -6397,6 +6426,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .multi_chip =3D true, .edsa_support =3D MV88E6XXX_EDSA_SUPPORTED, .ptp_support =3D true, + .qav =3D &mv88e6341_qav_info, .ops =3D &mv88e6341_ops, }, =20 @@ -6477,6 +6507,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .multi_chip =3D true, .edsa_support =3D MV88E6XXX_EDSA_SUPPORTED, .ptp_support =3D true, + .qav =3D &mv88e6352_qav_info, .ops =3D &mv88e6352_ops, }, [MV88E6361] =3D { @@ -6534,6 +6565,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .multi_chip =3D true, .edsa_support =3D MV88E6XXX_EDSA_UNDOCUMENTED, .ptp_support =3D true, + .qav =3D &mv88e6390_qav_info, .ops =3D &mv88e6390_ops, }, [MV88E6390X] =3D { @@ -6561,6 +6593,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .multi_chip =3D true, .edsa_support =3D MV88E6XXX_EDSA_UNDOCUMENTED, .ptp_support =3D true, + .qav =3D &mv88e6390_qav_info, .ops =3D &mv88e6390x_ops, }, =20 @@ -6589,6 +6622,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = =3D { .pvt =3D true, .multi_chip =3D true, .ptp_support =3D true, + .qav =3D &mv88e6390_qav_info, .ops =3D &mv88e6393x_ops, }, }; @@ -7210,6 +7244,112 @@ static int mv88e6xxx_crosschip_lag_leave(struct dsa= _switch *ds, int sw_index, return err_sync ? : err_pvt; } =20 +static int mv88e6xxx_setup_tc_cbs(struct dsa_switch *ds, int port, + struct tc_cbs_qopt_offload *cbs) +{ + const struct mv88e6xxx_avb_ops *avb_ops; + struct mv88e6xxx_chip *chip =3D ds->priv; + const struct mv88e6xxx_qav_info *qav; + const struct mv88e6xxx_ops *ops; + int hilimit_reg; + int rate_reg; + u8 queue_bit; + u32 rate =3D 0; + u16 hilimit; + int err; + + ops =3D chip->info->ops; + avb_ops =3D ops->avb_ops; + qav =3D chip->info->qav; + + if (!qav || !avb_ops || !avb_ops->port_qav_write || + !ops->port_set_scheduling_mode) + return -EOPNOTSUPP; + + if (!dsa_is_user_port(ds, port)) + return -EOPNOTSUPP; + + if (!(qav->queue_mask & BIT(cbs->queue))) { + NL_SET_ERR_MSG_MOD(cbs->extack, "CBS not supported on queue"); + return -EOPNOTSUPP; + } + + queue_bit =3D BIT(cbs->queue); + rate_reg =3D MV88E6XXX_PORT_QAV_CFG_RATE(cbs->queue); + hilimit_reg =3D MV88E6XXX_PORT_QAV_CFG_HILIMIT(cbs->queue); + + if (cbs->enable) { + if (cbs->hicredit <=3D 0 || + cbs->hicredit > qav->hilimit_mask) { + NL_SET_ERR_MSG_MOD(cbs->extack, + "hicredit out of range"); + return -ERANGE; + } + + rate =3D DIV_ROUND_UP(cbs->idleslope, qav->rate_unit); + if (rate > qav->rate_mask) { + NL_SET_ERR_MSG_MOD(cbs->extack, + "idleslope out of range"); + return -ERANGE; + } + /* avoid using zero rate */ + rate =3D max_t(u16, rate, 1); + } + + mv88e6xxx_reg_lock(chip); + + if (!cbs->enable) { + err =3D mv88e6xxx_port_qav_write(chip, port, rate_reg, 0); + if (err) + goto unlock; + + if (!(chip->ports[port].cbs_active_queues & ~queue_bit)) { + err =3D mv88e6xxx_port_set_scheduling_mode(chip, port, 0); + if (err) + goto unlock; + } + chip->ports[port].cbs_active_queues &=3D ~queue_bit; + goto unlock; + } + + hilimit =3D cbs->hicredit & qav->hilimit_mask; + err =3D mv88e6xxx_port_qav_write(chip, port, hilimit_reg, hilimit); + if (err) + goto unlock; + + err =3D mv88e6xxx_port_qav_write(chip, port, rate_reg, rate); + if (err) + goto unlock; + + if (!chip->ports[port].cbs_active_queues) { + u8 sched_mode =3D chip->info->num_tx_queues - 1; + + err =3D mv88e6xxx_port_set_scheduling_mode(chip, port, + sched_mode); + if (err) { + mv88e6xxx_port_qav_write(chip, port, rate_reg, 0); + goto unlock; + } + } + chip->ports[port].cbs_active_queues |=3D queue_bit; + +unlock: + mv88e6xxx_reg_unlock(chip); + + return err; +} + +static int mv88e6xxx_port_setup_tc(struct dsa_switch *ds, int port, + enum tc_setup_type type, void *type_data) +{ + switch (type) { + case TC_SETUP_QDISC_CBS: + return mv88e6xxx_setup_tc_cbs(ds, port, type_data); + default: + return -EOPNOTSUPP; + } +} + static const struct phylink_mac_ops mv88e6xxx_phylink_mac_ops =3D { .mac_select_pcs =3D mv88e6xxx_mac_select_pcs, .mac_prepare =3D mv88e6xxx_mac_prepare, @@ -7269,6 +7409,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_o= ps =3D { .port_hwtstamp_get =3D mv88e6xxx_port_hwtstamp_get, .port_txtstamp =3D mv88e6xxx_port_txtstamp, .port_rxtstamp =3D mv88e6xxx_port_rxtstamp, + .port_setup_tc =3D mv88e6xxx_port_setup_tc, .cls_flower_add =3D mv88e6xxx_cls_flower_add, .cls_flower_del =3D mv88e6xxx_cls_flower_del, .get_ts_info =3D mv88e6xxx_get_ts_info, diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/c= hip.h index 3a1d79a117dca..85f646efe75ee 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -125,6 +125,7 @@ enum mv88e6xxx_edsa_support { }; =20 struct mv88e6xxx_ops; +struct mv88e6xxx_qav_info; =20 struct mv88e6xxx_info { enum mv88e6xxx_family family; @@ -177,6 +178,9 @@ struct mv88e6xxx_info { /* Supports PTP */ bool ptp_support; =20 + /* 802.1Qav credit based shaping */ + const struct mv88e6xxx_qav_info *qav; + /* Internal PHY start index. 0 means that internal PHYs range starts at * port 0, 1 means internal PHYs range starts at port 1, etc */ @@ -304,6 +308,9 @@ struct mv88e6xxx_port { =20 /* MacAuth Bypass control flag */ bool mab; + + /* Queues with CBS currently enabled. */ + u8 cbs_active_queues; }; =20 enum mv88e6xxx_region_id { @@ -606,6 +613,8 @@ struct mv88e6xxx_ops { size_t size); =20 int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port); + int (*port_set_scheduling_mode)(struct mv88e6xxx_chip *chip, int port, + u8 mode); int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in, u8 out); int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port); @@ -763,6 +772,10 @@ struct mv88e6xxx_avb_ops { int (*tai_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data, int len); int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data); + + /* Access port-scoped 802.1Qav registers */ + int (*port_qav_write)(struct mv88e6xxx_chip *chip, int port, int addr, + u16 data); }; =20 struct mv88e6xxx_ptp_ops { @@ -798,6 +811,13 @@ struct mv88e6xxx_tcam_ops { int (*flush_tcam)(struct mv88e6xxx_chip *chip); }; =20 +struct mv88e6xxx_qav_info { + u16 rate_unit; /* in kbps */ + u16 rate_mask; /* QPri Rate valid bits mask */ + u16 hilimit_mask; /* QPri HiLimit bits mask*/ + u8 queue_mask; /* supported queues bitmask */ +}; + static inline bool mv88e6xxx_has_stu(struct mv88e6xxx_chip *chip) { return chip->info->max_sid > 0 && diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xx= x/global2.h index ff5adf7c9bc3a..df52ff3adc88c 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.h +++ b/drivers/net/dsa/mv88e6xxx/global2.h @@ -186,6 +186,9 @@ #define MV88E6352_G2_AVB_CMD_BLOCK_MASK 0x00e0 #define MV88E6352_G2_AVB_CMD_ADDR_MASK 0x001f =20 +#define MV88E6XXX_PORT_QAV_CFG_RATE(queue) (((queue) & 0x7) << 1) +#define MV88E6XXX_PORT_QAV_CFG_HILIMIT(queue) ((((queue) & 0x7) << 1) + 1) + /* Offset 0x17: AVB Data Register */ #define MV88E6352_G2_AVB_DATA 0x17 =20 diff --git a/drivers/net/dsa/mv88e6xxx/global2_avb.c b/drivers/net/dsa/mv88= e6xxx/global2_avb.c index 657783e043ff1..6b54e275d21ab 100644 --- a/drivers/net/dsa/mv88e6xxx/global2_avb.c +++ b/drivers/net/dsa/mv88e6xxx/global2_avb.c @@ -110,6 +110,15 @@ static int mv88e6352_g2_avb_port_ptp_write(struct mv88= e6xxx_chip *chip, return mv88e6xxx_g2_avb_write(chip, writeop, data); } =20 +static int mv88e6352_g2_avb_port_qav_write(struct mv88e6xxx_chip *chip, + int port, int addr, u16 data) +{ + u16 writeop =3D MV88E6352_G2_AVB_CMD_OP_WRITE | (port << 8) | + (MV88E6352_G2_AVB_CMD_BLOCK_QAV << 5) | addr; + + return mv88e6xxx_g2_avb_write(chip, writeop, data); +} + static int mv88e6352_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr, u16 *data, int len) { @@ -149,6 +158,7 @@ const struct mv88e6xxx_avb_ops mv88e6352_avb_ops =3D { .ptp_write =3D mv88e6352_g2_avb_ptp_write, .tai_read =3D mv88e6352_g2_avb_tai_read, .tai_write =3D mv88e6352_g2_avb_tai_write, + .port_qav_write =3D mv88e6352_g2_avb_port_qav_write, }; =20 static int mv88e6165_g2_avb_tai_read(struct mv88e6xxx_chip *chip, int addr, @@ -174,6 +184,7 @@ const struct mv88e6xxx_avb_ops mv88e6165_avb_ops =3D { .ptp_write =3D mv88e6352_g2_avb_ptp_write, .tai_read =3D mv88e6165_g2_avb_tai_read, .tai_write =3D mv88e6165_g2_avb_tai_write, + .port_qav_write =3D mv88e6352_g2_avb_port_qav_write, }; =20 static int mv88e6390_g2_avb_port_ptp_read(struct mv88e6xxx_chip *chip, @@ -197,6 +208,15 @@ static int mv88e6390_g2_avb_port_ptp_write(struct mv88= e6xxx_chip *chip, return mv88e6xxx_g2_avb_write(chip, writeop, data); } =20 +static int mv88e6390_g2_avb_port_qav_write(struct mv88e6xxx_chip *chip, + int port, int addr, u16 data) +{ + u16 writeop =3D MV88E6390_G2_AVB_CMD_OP_WRITE | (port << 8) | + (MV88E6352_G2_AVB_CMD_BLOCK_QAV << 5) | addr; + + return mv88e6xxx_g2_avb_write(chip, writeop, data); +} + static int mv88e6390_g2_avb_ptp_read(struct mv88e6xxx_chip *chip, int addr, u16 *data, int len) { @@ -236,4 +256,5 @@ const struct mv88e6xxx_avb_ops mv88e6390_avb_ops =3D { .ptp_write =3D mv88e6390_g2_avb_ptp_write, .tai_read =3D mv88e6390_g2_avb_tai_read, .tai_write =3D mv88e6390_g2_avb_tai_write, + .port_qav_write =3D mv88e6390_g2_avb_port_qav_write, }; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/p= ort.c index 4f915fbee228c..541fee492f5ff 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -1323,6 +1323,51 @@ int mv88e6097_port_egress_rate_limiting(struct mv88e= 6xxx_chip *chip, int port) 0x0001); } =20 +int mv88e6352_port_set_scheduling_mode(struct mv88e6xxx_chip *chip, int po= rt, + u8 mode) +{ + u16 reg; + int err; + + if (mode > 3) + return -EINVAL; + + err =3D mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_EGRESS_RATE_CTL2, + ®); + if (err) + return err; + + reg &=3D ~MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_MASK; + reg |=3D mode << MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_SHIFT; + + return mv88e6xxx_port_write(chip, port, + MV88E6XXX_PORT_EGRESS_RATE_CTL2, reg); +} + +int mv88e6390_port_set_scheduling_mode(struct mv88e6xxx_chip *chip, int po= rt, + u8 mode) +{ + u16 reg; + int err; + + if (mode > MV88E6390_PORT_QUEUE_CTL_SCHEDULE_MASK) + return -EINVAL; + + reg =3D MV88E6390_PORT_QUEUE_CTL_UPDATE | + (MV88E6390_PORT_QUEUE_CTL_SCHEDULE << + MV88E6390_PORT_QUEUE_CTL_PTR_SHIFT) | + (mode & MV88E6390_PORT_QUEUE_CTL_SCHEDULE_MASK); + + err =3D mv88e6xxx_port_write(chip, port, MV88E6390_PORT_QUEUE_CTL, + reg); + if (err) + return err; + + return mv88e6xxx_port_wait_bit(chip, port, MV88E6390_PORT_QUEUE_CTL, + __bf_shf(MV88E6390_PORT_QUEUE_CTL_UPDATE) + , 0); +} + /* Offset 0x0B: Port Association Vector */ =20 int mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip *chip, int port, @@ -1736,3 +1781,21 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip= *chip, int port, =20 return mv88e6393x_port_policy_write(chip, port, ptr, reg); } + +int mv88e6xxx_port_qav_write(struct mv88e6xxx_chip *chip, int port, int ad= dr, + u16 data) +{ + if (!chip->info->ops->avb_ops->port_qav_write) + return -EOPNOTSUPP; + + return chip->info->ops->avb_ops->port_qav_write(chip, port, addr, data); +} + +int mv88e6xxx_port_set_scheduling_mode(struct mv88e6xxx_chip *chip, int po= rt, + u8 mode) +{ + if (!chip->info->ops->port_set_scheduling_mode) + return -EOPNOTSUPP; + + return chip->info->ops->port_set_scheduling_mode(chip, port, mode); +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/p= ort.h index bd61ddf2b228a..010319cb8a25a 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -241,6 +241,18 @@ =20 /* Offset 0x0A: Egress Rate Control 2 */ #define MV88E6XXX_PORT_EGRESS_RATE_CTL2 0x0a +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_MASK 0x3000 +#define MV88E6XXX_PORT_EGRESS_RATE_CTL2_SCHEDULE_SHIFT 12 + +/* Offset 0x1C: Port Queue Control */ +#define MV88E6390_PORT_QUEUE_CTL 0x1c +#define MV88E6390_PORT_QUEUE_CTL_UPDATE 0x8000 +#define MV88E6390_PORT_QUEUE_CTL_PTR_MASK 0x7f00 +#define MV88E6390_PORT_QUEUE_CTL_PTR_SHIFT 8 +#define MV88E6390_PORT_QUEUE_CTL_DATA_MASK 0x00ff +#define MV88E6390_PORT_QUEUE_CTL_SCHEDULE 0x00 +#define MV88E6390_PORT_QUEUE_CTL_SCHEDULE_MASK 0x07 + =20 /* Offset 0x0B: Port Association Vector */ #define MV88E6XXX_PORT_ASSOC_VECTOR 0x0b @@ -562,6 +574,10 @@ int mv88e6165_port_set_jumbo_size(struct mv88e6xxx_chi= p *chip, int port, size_t size); int mv88e6095_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int p= ort); int mv88e6097_port_egress_rate_limiting(struct mv88e6xxx_chip *chip, int p= ort); +int mv88e6352_port_set_scheduling_mode(struct mv88e6xxx_chip *chip, int po= rt, + u8 mode); +int mv88e6390_port_set_scheduling_mode(struct mv88e6xxx_chip *chip, int po= rt, + u8 mode); int mv88e6xxx_port_set_assoc_vector(struct mv88e6xxx_chip *chip, int port, u16 pav); int mv88e6097_port_pause_limit(struct mv88e6xxx_chip *chip, int port, u8 i= n, @@ -606,5 +622,9 @@ int mv88e6xxx_port_hidden_read(struct mv88e6xxx_chip *c= hip, int block, int port, int reg, u16 *val); =20 int mv88e6xxx_port_enable_tcam(struct mv88e6xxx_chip *chip, int port); +int mv88e6xxx_port_qav_write(struct mv88e6xxx_chip *chip, int port, int ad= dr, + u16 data); +int mv88e6xxx_port_set_scheduling_mode(struct mv88e6xxx_chip *chip, int po= rt, + u8 mode); =20 #endif /* _MV88E6XXX_PORT_H */ --=20 2.43.0