From nobody Mon Feb 9 19:25:47 2026 Received: from SJ2PR03CU001.outbound.protection.outlook.com (mail-westusazon11012056.outbound.protection.outlook.com [52.101.43.56]) (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 180AD3624BB; Thu, 18 Dec 2025 15:58:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.43.56 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766073521; cv=fail; b=bytnoEyS/vtT96q47ILQ8LC+TvIbC6kAuL1jpXzOE74cucLz+NUssm3xHTc1DHj6Fb7Sh5giQB++MWhAoTe9hM6ygwq1TjAEJAgsBAgILdm1IqZc7KeA5EBzexZUybghHZUQsTjxZ5NCTkgg+NXkDTrjjLtmnF/Kekz3yXIHLkA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766073521; c=relaxed/simple; bh=1z5ZiG+eRhsyll0FQwl6z3RVyxyF1nf1Uhk9c5wuwF8=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=I4NMTv8xQQriVvfcdozgxmfzBs+DaH6Vy2swNvTUNu7x3zv2oKWl+/F0SGSQmEoAzZyhrOGsgnuQJpIAh+fNwB1SbuYKFLZQ/PazwSMIexBqei8TbH3LUMK1EsndfWn+A3bkA9KlFVL3hce4EQHfb5PWa9S30lBoM1CJjqXLKT4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=jW85R0MZ; arc=fail smtp.client-ip=52.101.43.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="jW85R0MZ" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=d9Sv+EOzGylK/VejCxsGu6VyWFXDa3dF6hZK7gVv2W7z8FwzSzHdpBMjt5LaXnA7+IsziwMxP1sNnCWk8oZZhcejb6IKuhpr3uACpOFBVlu4YHziOozujFpNDxuAdHq+lJEEWJrRtOyFFjZQChAjNw9ujwxrhVZ2VDMn05PL//OHiWl489UI98iyAYS9lrAS1TN29R3OqjwF3euwdu06vGeYpckrDgAmeNGzmyP9M79xKL+vMx7aZkrd8NOdt1oChhkCf43UEA6Lkv8VLAD4JKx8Xjr9sABGzCsSsnSJpRmAOjzMlmnlxBtFiARtkaSZQM3qL/nQNT0KJQu2WUzb1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=kJccDAGKZNIBU8P+sxdIsnRlgNtx6sW/6sHW8aQrXgE=; b=b/iJ7URnyErvdHaZFEtqN1a/TRt7KiAUB4D5mhat9E51qFZBW19h5GtNZhLjOyy4lfvCF7ijAmJM6wjBY7neLYqKg+UpAqpalMagMnE/GXKVORtmy1Ny2mEmdzCppuOmIeizh80dpbSsWVFBkZ890GYMkfwGaf0Xn1eUGC898JHBqIdfUsagHEGagDaoJ/K91P80hS+eETzHyGT0SkqUaczVI7tj1Y2aVu5XFQNZ3m4viPv4ETzS/F4OKBeg0yzk/429z8+ajuEkcaKS1MkU2/aot6er4h3pLR+ACLvtJVW16uTuEtedgJRF1Ax1oCHm4t7ddlDLJar0k6aUuqYCLQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.118.233) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kJccDAGKZNIBU8P+sxdIsnRlgNtx6sW/6sHW8aQrXgE=; b=jW85R0MZSkqtvGwgdIyplKXdIkhxnaKNQTVZ+IitA2vYh/ZyjRej/6AiKCJYofZn33/uT/cnaGSYAf6e8z8+xKpEPzRSHW6ZKpJ5JsIew7RP3QOyAyw6rSlxZK+vol26oTw19HHj8WLj7AUOXjJkuwVpXCcG97VOUnl4QBVy+WoKTsicguMMSpf9STVz5/lVSJ6ce9Fai8pqAn3CB0JxjhKLEGhkHXMtpB76zQ4XdAzf3c0PtPK08RRhTCLbuiyxOHqbkP2N4oau8AZKLbtDViJh9DVSAmtvKVsn9249JndwZELX6YvxfUdgepyReNp5vYXyk0L3dzmLXAHAbrpKqA== Received: from PH8P220CA0032.NAMP220.PROD.OUTLOOK.COM (2603:10b6:510:348::10) by PH7PR12MB9176.namprd12.prod.outlook.com (2603:10b6:510:2e9::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9434.6; Thu, 18 Dec 2025 15:58:29 +0000 Received: from CY4PEPF0000EE32.namprd05.prod.outlook.com (2603:10b6:510:348:cafe::60) by PH8P220CA0032.outlook.office365.com (2603:10b6:510:348::10) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9434.8 via Frontend Transport; Thu, 18 Dec 2025 15:58:39 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.118.233) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.118.233 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.118.233; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.118.233) by CY4PEPF0000EE32.mail.protection.outlook.com (10.167.242.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9434.6 via Frontend Transport; Thu, 18 Dec 2025 15:58:29 +0000 Received: from drhqmail202.nvidia.com (10.126.190.181) by mail.nvidia.com (10.127.129.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Thu, 18 Dec 2025 07:58:11 -0800 Received: from drhqmail203.nvidia.com (10.126.190.182) by drhqmail202.nvidia.com (10.126.190.181) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Thu, 18 Dec 2025 07:58:11 -0800 Received: from vdi.nvidia.com (10.127.8.10) by mail.nvidia.com (10.126.190.182) with Microsoft SMTP Server id 15.2.2562.20 via Frontend Transport; Thu, 18 Dec 2025 07:58:06 -0800 From: Edward Srouji To: , Leon Romanovsky , Saeed Mahameed , Tariq Toukan , Mark Bloch , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Jason Gunthorpe CC: , , , Or Har-Toov , "Maher Sanalla" Subject: [PATCH mlx5-next 02/10] net/mlx5: Propagate LAG effective max_tx_speed to vports Date: Thu, 18 Dec 2025 17:58:05 +0200 Message-ID: <20251218-vf-bw-lag-mode-v1-2-7d8ed4368bea@nvidia.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20251218-vf-bw-lag-mode-v1-0-7d8ed4368bea@nvidia.com> References: <20251218-vf-bw-lag-mode-v1-0-7d8ed4368bea@nvidia.com> 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" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1766069544; l=12727; i=edwards@nvidia.com; s=20251029; h=from:subject:message-id; bh=Awua+wWYDe386DrscYUnPCv6WF2teNaNDM2UWKYe7VM=; b=CEOVh9ELN31riAsdjOu98m3WYy4j6fN0ygCVYiBQ5FkK4su+SlowVQduADRf/ABVqxkEq0JHL kJEIye4Y4PLDbFv0HM4WAYZJ7njuehBx4U648T7+eQhXRmP8j7j/9gc X-Developer-Key: i=edwards@nvidia.com; a=ed25519; pk=VME+d2WbMZT5AY+AolKh2XIdrnXWUwwzz/XLQ3jXgDM= Content-Transfer-Encoding: quoted-printable X-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CY4PEPF0000EE32:EE_|PH7PR12MB9176:EE_ X-MS-Office365-Filtering-Correlation-Id: b127398a-ef91-42e6-5fc3-08de3e4e4978 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700013|7416014|376014|82310400026|1800799024|921020; X-Microsoft-Antispam-Message-Info: =?utf-8?B?YjBGWUEvRldBbXFBQTFDWGhRSFZlOG8zMGdNWFRLc1Jza1JVUnNuY3hmVzR6?= =?utf-8?B?a2x0ckRDREp5NmpTYVRyWHhwT0lENEg3SCtxelZ3eHFscHM1WSt4VHFRNDRh?= =?utf-8?B?Q0tDaGRGVC9EcHF0Y3U0bmJSdkg4MDR5c2IyMkFsS1UrdEJ0cEZJUDd3M0s4?= =?utf-8?B?YmR4cFJhWEFMMUo0d08ySysvd1ZaM054RUsxdC8rZmdYT2hCa3hwaUd5UXZ6?= =?utf-8?B?ME9qZ29lUmdUczZXdmd4UGFleEF4bTFFcE8rNzFRK2FwbnY1cWtGYmFTdElp?= =?utf-8?B?cFk1NTUvWGxWbTEvWWZENjBsaTVGeFQ1MjBsbDgwMkMwa1locXJPNEpWTE1y?= =?utf-8?B?S0dXRWZnWmlvL1FjTk9WWUJsOTdkTHBrbE1PTU1OaGs2SHlhc3MrZGZUZXpm?= =?utf-8?B?VHRZeG9maFd3RENMUjBSdy8wdkJBei9jeEFnTGpNcE5uZmJPdlRIbnpTcmZr?= =?utf-8?B?L3Nvby9VWHZxcGdITGp2WmhTYUhOQU1KZDRMZCtDUDhWYzF5M0VtQlBvSG5l?= =?utf-8?B?dkpoU25RbTdCNkl6a3hEN2N1LytUWjV0cWtJcXlsZ0VJV1pGd1Rnb2xtRndw?= =?utf-8?B?ZkVFV3FYNzdkVFNVVUxScXpjR1dKNkxhUW1qZ0hGdEhleSswbEFxS0FOclBn?= =?utf-8?B?V2xMaHAwQ2tjbDVvWE85ZWFKT1VtWXUwdklicnd1ZmJnemdJazZMVzlKTzAx?= =?utf-8?B?djVvL1pUT0lSaHBrTi9rSXFhQmtSWU9pbTUyZEFXcTI3a1dNUkxMeitWNU0r?= =?utf-8?B?TG5ic3poWTBscXV5eTBhbWpvK09kYXhaaENzYlFnb2w0a2NMSjJZc25hWDFn?= =?utf-8?B?ZDJhUE9BY2l2NGZ2UmVqUGczMTdjakVHbHVOK0NIMWRJUGdhVlJObnJqc0M1?= =?utf-8?B?WjNackJSaUFsL2RBNzhac0ZjRGRwREF3emIwa0tYUFVrZ3ZWRGZrS1B1UDBB?= =?utf-8?B?dUN3M3o3VzJJWnluOWszYmhwUklwbVZmMzFHd2gyU2h1dFNmVFFJdDMvbVRu?= =?utf-8?B?Y0ZSTTBqNzVQU0xyZVJEUDhHZWQ4L3ptZi9iZkliM0s5NWxwMUJxem0vQmZ4?= =?utf-8?B?YXlGMkNXYmJHSnBGT3pZRy80RWRWVExQL21tTHQ4VW9mb01ZY3VOaTlHMzcw?= =?utf-8?B?NEJQMjFUd3Nnd2piNG16SkJXRFVaZk5MOG5pMmRKNlh2Y3RrcHFBZkR5dG5E?= =?utf-8?B?L250bk9WcEpyYU5vSDRKMjBlS0VrZkxaMjdYSG83S3BGdEpqRHVReTRLQjAw?= =?utf-8?B?M1JJWS9wUUQ3S2JiZGw0UzQwSlVZT2dxMkcxK0Q5UVRRUDBrVnVydHBxTHdj?= =?utf-8?B?dThFT1ZwYldnSUJZQndqck00a0dKZnNCKzgyOFd4bngyNDNoWEcwenRPZFUw?= =?utf-8?B?eHlnenBxTFNTenBMSEFNaDgxdVkzOHFGbnBZWVk0U1pmcTdHc3ZvMkRWMENJ?= =?utf-8?B?SmZ1VG42Y1FIRE9hRDRrQ1Y2OWZYdDZTY3pnVUlmRE1LZzltaVc5bjh6aWwv?= =?utf-8?B?UTgzZWNWZXpudmhLUTdSbWd5L2VCV3V5ZSs1aldBaG1kbkdmVDh0c3d4WmJj?= =?utf-8?B?Q2dhaG5yZ2ZWd0x4RWxHckFNazJZWlNNcnBTV3JhalE5anFVbXA0SFN5dHg3?= =?utf-8?B?NUNVRU1HV0JUc0k3WjBsWEEzQlljYUVsOXN3N25HMUZFbWFPODdOWHhYWjRO?= =?utf-8?B?cklaQm9JZlZOZkJKNWdBQUhBZDRQY0c0ejFHWndYTVhKcTRwOTF3M3lSMXAv?= =?utf-8?B?bSt6amJpR3hrVUk1NDhPRFlXMDRoT3pvOXpoVVZzcDhNRDd0ZzBHcmhQcGFC?= =?utf-8?B?YTZnQVVUQWFlQnhxYkEyczdUSmhIRVkxR2oweml1YUZYb1dCeUQ0YVE1aW5K?= =?utf-8?B?dFA0UWRRWDdCUytEeWo3TXd0ZW5MaGg0b25CZzNGcy9tK3FqVllRZS9MNDZo?= =?utf-8?B?MHZpcTRCVU83SVhwSlRodVVVTjNPTUxqMXoydFlvaHlwaXVqaEZDdEV5TDdU?= =?utf-8?B?a3hCL09pV0Z6a0EyZGRrUEJWeDVNNUxWVHVGRmx6Y2wxQndEekNtTUlWU3Ro?= =?utf-8?B?MzMrTHp2Y1VWZnNVRXZzVHZpaVIyNjNrLzZmKzJ5ZUp1RkJwWExCdXE0eExG?= =?utf-8?Q?YLuYIfDsbh/D9M9h7nUzTyMR6?= X-Forefront-Antispam-Report: CIP:216.228.118.233;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge2.nvidia.com;CAT:NONE;SFS:(13230040)(36860700013)(7416014)(376014)(82310400026)(1800799024)(921020);DIR:OUT;SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Dec 2025 15:58:29.3222 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: b127398a-ef91-42e6-5fc3-08de3e4e4978 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.233];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: CY4PEPF0000EE32.namprd05.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH7PR12MB9176 From: Or Har-Toov Currently, vports report only their parent's uplink speed, which in LAG setups does not reflect the true aggregated bandwidth. This makes it hard for upper-layer software to optimize load balancing decisions based on accurate bandwidth information. Fix the issue by calculating the possible maximum speed of a LAG as the sum of speeds of all active uplinks that are part of the LAG. Propagate this effective max speed to vports associated with the LAG whenever a relevant event occurs, such as physical port link state changes or LAG creation/modification. With this change, upper-layer components receive accurate bandwidth information corresponding to the active members of the LAG and can make better load balancing decisions. Signed-off-by: Or Har-Toov Reviewed-by: Maher Sanalla Reviewed-by: Mark Bloch Signed-off-by: Edward Srouji --- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 158 +++++++++++++++++= ++++ drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h | 9 ++ .../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 1 + drivers/net/ethernet/mellanox/mlx5/core/port.c | 24 ++++ drivers/net/ethernet/mellanox/mlx5/core/vport.c | 45 ++++++ include/linux/mlx5/vport.h | 4 + 6 files changed, 241 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/ne= t/ethernet/mellanox/mlx5/core/lag/lag.c index 1ac933cd8f02..a042612dcde6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -996,6 +996,126 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_l= ag *ldev, bool do_bond) ldev->mode !=3D MLX5_LAG_MODE_MPESW; } =20 +#ifdef CONFIG_MLX5_ESWITCH +static int +mlx5_lag_sum_devices_speed(struct mlx5_lag *ldev, u32 *sum_speed, + int (*get_speed)(struct mlx5_core_dev *, u32 *)) +{ + struct mlx5_core_dev *pf_mdev; + int pf_idx; + u32 speed; + int ret; + + *sum_speed =3D 0; + mlx5_ldev_for_each(pf_idx, 0, ldev) { + pf_mdev =3D ldev->pf[pf_idx].dev; + if (!pf_mdev) + continue; + + ret =3D get_speed(pf_mdev, &speed); + if (ret) { + mlx5_core_dbg(pf_mdev, + "Failed to get device speed using %ps. Device %s speed is not av= ailable (err=3D%d)\n", + get_speed, dev_name(pf_mdev->device), + ret); + return ret; + } + + *sum_speed +=3D speed; + } + + return 0; +} + +static int mlx5_lag_sum_devices_max_speed(struct mlx5_lag *ldev, u32 *max_= speed) +{ + return mlx5_lag_sum_devices_speed(ldev, max_speed, + mlx5_port_max_linkspeed); +} + +static void mlx5_lag_modify_device_vports_speed(struct mlx5_core_dev *mdev, + u32 speed) +{ + u16 op_mod =3D MLX5_VPORT_STATE_OP_MOD_ESW_VPORT; + struct mlx5_eswitch *esw =3D mdev->priv.eswitch; + struct mlx5_vport *vport; + unsigned long i; + int ret; + + if (!esw) + return; + + if (!MLX5_CAP_ESW(mdev, esw_vport_state_max_tx_speed)) + return; + + mlx5_esw_for_each_vport(esw, i, vport) { + if (!vport) + continue; + + if (vport->vport =3D=3D MLX5_VPORT_UPLINK) + continue; + + ret =3D mlx5_modify_vport_max_tx_speed(mdev, op_mod, + vport->vport, true, speed); + if (ret) + mlx5_core_dbg(mdev, + "Failed to set vport %d speed %d, err=3D%d\n", + vport->vport, speed, ret); + } +} + +void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev) +{ + struct mlx5_core_dev *mdev; + u32 speed; + int pf_idx; + + speed =3D ldev->tracker.bond_speed_mbps; + + if (speed =3D=3D SPEED_UNKNOWN) + return; + + /* If speed is not set, use the sum of max speeds of all PFs */ + if (!speed && mlx5_lag_sum_devices_max_speed(ldev, &speed)) + return; + + speed =3D speed / MLX5_MAX_TX_SPEED_UNIT; + + mlx5_ldev_for_each(pf_idx, 0, ldev) { + mdev =3D ldev->pf[pf_idx].dev; + if (!mdev) + continue; + + mlx5_lag_modify_device_vports_speed(mdev, speed); + } +} + +void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev) +{ + struct mlx5_core_dev *mdev; + u32 speed; + int pf_idx; + int ret; + + mlx5_ldev_for_each(pf_idx, 0, ldev) { + mdev =3D ldev->pf[pf_idx].dev; + if (!mdev) + continue; + + ret =3D mlx5_port_oper_linkspeed(mdev, &speed); + if (ret) { + mlx5_core_dbg(mdev, + "Failed to reset vports speed for device %s. Oper speed is not a= vailable (err=3D%d)\n", + dev_name(mdev->device), ret); + continue; + } + + speed =3D speed / MLX5_MAX_TX_SPEED_UNIT; + mlx5_lag_modify_device_vports_speed(mdev, speed); + } +} +#endif + static void mlx5_do_bond(struct mlx5_lag *ldev) { int idx =3D mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); @@ -1083,9 +1203,12 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) ndev); dev_put(ndev); } + mlx5_lag_set_vports_agg_speed(ldev); } else if (mlx5_lag_should_modify_lag(ldev, do_bond)) { mlx5_modify_lag(ldev, &tracker); + mlx5_lag_set_vports_agg_speed(ldev); } else if (mlx5_lag_should_disable_lag(ldev, do_bond)) { + mlx5_lag_reset_vports_speed(ldev); mlx5_disable_lag(ldev); } } @@ -1286,6 +1409,38 @@ static int mlx5_handle_changeinfodata_event(struct m= lx5_lag *ldev, return 1; } =20 +static void mlx5_lag_update_tracker_speed(struct lag_tracker *tracker, + struct net_device *ndev) +{ + struct ethtool_link_ksettings lksettings; + struct net_device *bond_dev; + int err; + + if (netif_is_lag_master(ndev)) + bond_dev =3D ndev; + else + bond_dev =3D netdev_master_upper_dev_get(ndev); + + if (!bond_dev) { + tracker->bond_speed_mbps =3D SPEED_UNKNOWN; + return; + } + + err =3D __ethtool_get_link_ksettings(bond_dev, &lksettings); + if (err) { + netdev_dbg(bond_dev, + "Failed to get speed for bond dev %s, err=3D%d\n", + bond_dev->name, err); + tracker->bond_speed_mbps =3D SPEED_UNKNOWN; + return; + } + + if (lksettings.base.speed =3D=3D SPEED_UNKNOWN) + tracker->bond_speed_mbps =3D 0; + else + tracker->bond_speed_mbps =3D lksettings.base.speed; +} + /* this handler is always registered to netdev events */ static int mlx5_lag_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -1317,6 +1472,9 @@ static int mlx5_lag_netdev_event(struct notifier_bloc= k *this, break; } =20 + if (changed) + mlx5_lag_update_tracker_speed(&tracker, ndev); + ldev->tracker =3D tracker; =20 if (changed) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/ne= t/ethernet/mellanox/mlx5/core/lag/lag.h index 4918eee2b3da..8de5640a0161 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -48,6 +48,7 @@ struct lag_tracker { unsigned int is_bonded:1; unsigned int has_inactive:1; enum netdev_lag_hash hash_type; + u32 bond_speed_mbps; }; =20 /* LAG data of a ConnectX card. @@ -116,6 +117,14 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev); void mlx5_lag_add_devices(struct mlx5_lag *ldev); struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *lde= v); =20 +#ifdef CONFIG_MLX5_ESWITCH +void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev); +void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev); +#else +static inline void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev) {} +static inline void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev) {} +#endif + static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev) { if (!MLX5_CAP_GEN(dev, vport_group_manager) || diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/= net/ethernet/mellanox/mlx5/core/mlx5_core.h index cfebc110c02f..9fdb9a543cf1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -381,6 +381,7 @@ const struct mlx5_link_info *mlx5_port_ptys2info(struct= mlx5_core_dev *mdev, u32 mlx5_port_info2linkmodes(struct mlx5_core_dev *mdev, struct mlx5_link_info *info, bool force_legacy); +int mlx5_port_oper_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); int mlx5_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed); =20 #define MLX5_PPS_CAP(mdev) (MLX5_CAP_GEN((mdev), pps) && \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/e= thernet/mellanox/mlx5/core/port.c index 85a9e534f442..83044c9b6b41 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -1200,6 +1200,30 @@ u32 mlx5_port_info2linkmodes(struct mlx5_core_dev *m= dev, return link_modes; } =20 +int mlx5_port_oper_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) +{ + const struct mlx5_link_info *table; + struct mlx5_port_eth_proto eproto; + u32 oper_speed =3D 0; + u32 max_size; + bool ext; + int err; + int i; + + ext =3D mlx5_ptys_ext_supported(mdev); + err =3D mlx5_port_query_eth_proto(mdev, 1, ext, &eproto); + if (err) + return err; + + mlx5e_port_get_link_mode_info_arr(mdev, &table, &max_size, false); + for (i =3D 0; i < max_size; ++i) + if (eproto.oper & MLX5E_PROT_MASK(i)) + oper_speed =3D max(oper_speed, table[i].speed); + + *speed =3D oper_speed; + return 0; +} + int mlx5_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) { const struct mlx5_link_info *table; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/= ethernet/mellanox/mlx5/core/vport.c index 306affbcfd3b..78b1b291cfa4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -62,6 +62,28 @@ u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8= opmod, u16 vport) return MLX5_GET(query_vport_state_out, out, state); } =20 +static int mlx5_query_vport_admin_state(struct mlx5_core_dev *mdev, u8 opm= od, + u16 vport, u8 other_vport, + u8 *admin_state) +{ + u32 out[MLX5_ST_SZ_DW(query_vport_state_out)] =3D {}; + u32 in[MLX5_ST_SZ_DW(query_vport_state_in)] =3D {}; + int err; + + MLX5_SET(query_vport_state_in, in, opcode, + MLX5_CMD_OP_QUERY_VPORT_STATE); + MLX5_SET(query_vport_state_in, in, op_mod, opmod); + MLX5_SET(query_vport_state_in, in, vport_number, vport); + MLX5_SET(query_vport_state_in, in, other_vport, other_vport); + + err =3D mlx5_cmd_exec_inout(mdev, query_vport_state, in, out); + if (err) + return err; + + *admin_state =3D MLX5_GET(query_vport_state_out, out, admin_state); + return 0; +} + int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport, u8 other_vport, u8 state) { @@ -77,6 +99,29 @@ int mlx5_modify_vport_admin_state(struct mlx5_core_dev *= mdev, u8 opmod, return mlx5_cmd_exec_in(mdev, modify_vport_state, in); } =20 +int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod, + u16 vport, u8 other_vport, u16 max_tx_speed) +{ + u32 in[MLX5_ST_SZ_DW(modify_vport_state_in)] =3D {}; + u8 admin_state; + int err; + + err =3D mlx5_query_vport_admin_state(mdev, opmod, vport, other_vport, + &admin_state); + if (err) + return err; + + MLX5_SET(modify_vport_state_in, in, opcode, + MLX5_CMD_OP_MODIFY_VPORT_STATE); + MLX5_SET(modify_vport_state_in, in, op_mod, opmod); + MLX5_SET(modify_vport_state_in, in, vport_number, vport); + MLX5_SET(modify_vport_state_in, in, other_vport, other_vport); + MLX5_SET(modify_vport_state_in, in, admin_state, admin_state); + MLX5_SET(modify_vport_state_in, in, max_tx_speed, max_tx_speed); + + return mlx5_cmd_exec_in(mdev, modify_vport_state, in); +} + static int mlx5_query_nic_vport_context(struct mlx5_core_dev *mdev, u16 vp= ort, bool other_vport, u32 *out) { diff --git a/include/linux/mlx5/vport.h b/include/linux/mlx5/vport.h index f876bfc0669c..2acf10e9f60a 100644 --- a/include/linux/mlx5/vport.h +++ b/include/linux/mlx5/vport.h @@ -41,6 +41,8 @@ (MLX5_CAP_GEN(mdev, port_type) =3D=3D MLX5_CAP_PORT_TYPE_ETH) && \ mlx5_core_is_pf(mdev)) =20 +#define MLX5_MAX_TX_SPEED_UNIT 100 + enum { MLX5_CAP_INLINE_MODE_L2, MLX5_CAP_INLINE_MODE_VPORT_CONTEXT, @@ -58,6 +60,8 @@ enum { u8 mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport); int mlx5_modify_vport_admin_state(struct mlx5_core_dev *mdev, u8 opmod, u16 vport, u8 other_vport, u8 state); +int mlx5_modify_vport_max_tx_speed(struct mlx5_core_dev *mdev, u8 opmod, + u16 vport, u8 other_vport, u16 max_tx_speed); int mlx5_query_nic_vport_mac_address(struct mlx5_core_dev *mdev, u16 vport, bool other, u8 *addr); int mlx5_query_mac_address(struct mlx5_core_dev *mdev, u8 *addr); --=20 2.47.1