From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-6.cisco.com (alln-iport-6.cisco.com [173.37.142.93]) (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 93DE248A2B3; Wed, 13 May 2026 15:17:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.93 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685432; cv=none; b=T2gbcmGI0VpRGVUngy9HToWkAeJmTxMe8N9e8I8yjrQ+OBIrbYxKXrixhJVrzgQkN29Hpbyq47QR9UEyCoHkZqcHN1YdLaFeCmhBwDNyyumMgEMJ9TJalAJ0Onz4rIbQXZasxF18E+j0a1GejHJyT8tAXYIPHU0i4CcCeDaYFcw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685432; c=relaxed/simple; bh=ZXSTJ7b/38rgvmYO873buvlool6i84d5a2ZJr/9ipT8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QeVMnQnpJenJ/DkBbkA3IluoTh7Jh/7/RtSGtDZ2nmao6NR+nEeeBuXDHlahuPy3Z4IIQbsSA+tQ6rc9BS66FjpcPZ6Mli/bkn4Fo++G/N7/j/q/vLYQSuYt8n4cAyxiY96ZjaEm1WX47djNzN9vA+I2kFy/iQ2eu3LHSh2TQCA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=K8cXbqVD; arc=none smtp.client-ip=173.37.142.93 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="K8cXbqVD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=2512; q=dns/txt; s=iport01; t=1778685430; x=1779895030; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=Ks0lsgTrBdaqV3gPaDF/jXpyLgWa4qOq0Cl3j1wSwFo=; b=K8cXbqVDsezk6vXedQNFZs90DTuq7JG6/OrX0aS/Fgxvm3BLD58gk63i elC+k8RA68m06HP4ONT8ZCkaWlZkEsYhCB1nb2RqoDu6tK6IEH8ztsyFo CYYQlLGOZXKSR85yK53oEIIAj1LRFt3QMLT9FAUaHpVXRy2KQhcE29Vvk UfAqkbqh7FLWGibLrYetkdkKGAnrtPm32SykzV+LlnYJUnNct7Rwu/YsU Fa5G1nKL0mjqyggsxl47ybT/LLFyS7bP9/GI4jTuRut9f1DClAqooUCAS lqwInt86EgAoojSo6Hez81nEEJm7GAfWT+gc59hMDUaI8wI9angmLO28/ g==; X-CSE-ConnectionGUID: IQ6p2cuGRaWMtEcw5YwUTQ== X-CSE-MsgGUID: lxTTmaoLQFiRH0JwJwW2IA== X-IPAS-Result: =?us-ascii?q?A0BFAgCnlARq/5D/Ja1aHgEBCxIMggULgleBUENJhFePU?= =?us-ascii?q?4Ihnh2Bfw8BAQEPUQQBAYUGAo0yAiY0CQ4BAgQDAgMBAQEBAQEBAQEBAQsBA?= =?us-ascii?q?QUBAQECAQcFgQ4ThlyGWwIBAyMEUhAlAiYCAkYQBgESgwKCdAOzDHp/M4EBh?= =?us-ascii?q?H3ZRIFkAQsUAYEKLoVygmcBgXCEBjuEQCcbgUlEhH2ECoQUgmkEgxwUjngJP?= =?us-ascii?q?4ECHANZLAFVEw0KCwcFYVIzAyAKCxISGBUCFC8PBBYyHXAMJxIsFzNYGwcFg?= =?us-ascii?q?UuCBXIUMQQhgQKEX3gjLANOgUMDCxgNSBEsNwYOGwQ9AW4Hij8dD4E/cT1Sg?= =?us-ascii?q?mgpk0CDMo1da6EOhCaBZKAOATKXZpMFLJhaIqNPMTeEaIFoPIFZMxoIGxWDI?= =?us-ascii?q?lMZD44tFhzMHycyPwcCBw4CkXOBfQEB?= IronPort-Data: A9a23:sunFdqNaoVEpGJjvrR14lsFynXyQoLVcMsEvi/4bfWQNrUomhjEAz zEcCGiBbvrbMzb8f4xzOdu1/RtTuZ6Bm9ExQXM5pCpnJ55oRWUpJjg4wmPYZX76whjrFRo/h ykmQoCeaphyFTmE+kvF3oHJ9RFUzbuPSqf3FNnKMyVwQR4MYCo6gHqPocZh6mJTqYb/WVjlV e/a+ZWFZgf4gmUsawr41orawP9RlKWq0N8nlgRWicBj5Df2i3QTBZQDEqC9R1OQapVUBOOzW 9HYx7i/+G7Dlz91Yj9yuu+mGqGiaue60Tmm0hK6aYD76vRxjnBaPpIACRYpQRw/ZwNlMDxG4 I4lWZSYEW/FN0BX8QgXe0Ew/ypWZcWq9FJbSJSymZT78qHIT5fj69RXUllsNpA3wO9IJH1j/ uNFGS8wUinW0opawJrjIgVtrt4oIM+uOMYUvWttiGmGS/0nWpvEBa7N4Le03h9p2ZsIRqmYP ZdEL2MzMHwsYDUXUrsTIIk3gOazhnr/WzZZs1mS46Ew5gA/ySQui+i9boaPJYTiqcN9mlakm mfP+EDALBAgFIS91hiazSiNr7qa9c/8cMdIfFGizdZmiUOew0QfAQMbUF+8r+X/jEOiM/pbJ k0I8y0GoaU49UWtCN7nUHWQrXKZuxcOVsZ4HOo95wWAjKHT5m6xBXUORxZCZcYguctwQiYlv neAmd/zCCMstrCJRX+D3rOJqzX0Mih9BXcLbyICTCMf7tXjqZ11hRXKJv5nEaionpj2FCv2z jSisicznfMQgNQN2qH9+krI6xqqq4TFQxAd+AraRCSm4xl/aYrjYJangWU39t5aJ4qfC13Et 38elo3Gs6YFDIqGk2qGR+Bl8KyV2stp+Qb02TZHd6TNPRz0k5J/Vei8OA1DGXo= IronPort-HdrOrdr: A9a23:I0f3WaBgZVcb+CjlHela55DYdb4zR+YMi2TDGXoBLSC9Ffb4qy nOppomPHDP5Qr5NEtLpTnEAtjjfZq+z/FICPcqXYtKNTOO0ACVxcNZnOjfKlbbdxEWmNQtsJ tIQuxSBML9CF5igd2/wgWpeuxQueWvweSEifjTynF1QRovUaFv6A9lFh2We3cGIjWufaBJc6 a0145guyeqf2gRY4CQA3kIWPWGmvjw/aiWGSLvw3UcmXOzZfTC0s+ALySl X-Talos-CUID: =?us-ascii?q?9a23=3A/aWCJWg0SeH91c4GP49utRquFDJuU0SD1C3bPmC?= =?us-ascii?q?CAFlMVJCeVgKh555Yqp87?= X-Talos-MUID: 9a23:8B8rXQlE5rRwputNpqspdnpmJPtU5q2pLHkjkK8m4+ubFzNPYRa02WE= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="738864270" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-6.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:01 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id DFE6618000488; Wed, 13 May 2026 15:16:00 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:38 -0700 Subject: [PATCH net-next v7 01/10] enic: verify firmware supports V2 SR-IOV at probe time 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-1-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat , Breno Leitao X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=2560; i=satishkh@cisco.com; h=from:subject:message-id; bh=ZXSTJ7b/38rgvmYO873buvlool6i84d5a2ZJr/9ipT8=; b=MSKkInVxZuIElMBIkob/qj/611krs0sY/clVnTdAZ2FS2XmDRI22UTRTEdkjdd/mJK+zM9ZtT sThThUrX8M5BQHMTetSwfzm3MREO3L8HNb8QS1y5rKCX0uHClBsEyEN X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com During PF probe, query the firmware get-supported-feature interface to verify that the running firmware supports V2 SR-IOV. Firmware version 5.3(4.72) and later report VIC_FEATURE_SRIOV via CMD_GET_SUPP_FEATURE_VER. If the firmware does not support the feature, set vf_type to ENIC_VF_TYPE_NONE and log a warning so the admin knows a firmware upgrade is needed. The VIC_FEATURE_SRIOV enum value (4) matches the firmware ABI. A placeholder entry (VIC_FEATURE_PTP at position 3) is added to keep the enum in sync with firmware's feature numbering. Suggested-by: Breno Leitao Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic_main.c | 21 ++++++++++++++++++++- drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 2 ++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethe= rnet/cisco/enic/enic_main.c index e7125b818087..53d68272d06a 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -2641,8 +2641,10 @@ static void enic_iounmap(struct enic *enic) static void enic_sriov_detect_vf_type(struct enic *enic) { struct pci_dev *pdev =3D enic->pdev; - int pos; + u64 supported_versions, a1 =3D 0; u16 vf_dev_id; + int pos; + int err; =20 if (enic_is_sriov_vf(enic) || enic_is_dynamic(enic)) return; @@ -2669,6 +2671,23 @@ static void enic_sriov_detect_vf_type(struct enic *e= nic) enic->vf_type =3D ENIC_VF_TYPE_NONE; break; } + + if (enic->vf_type !=3D ENIC_VF_TYPE_V2) + return; + + /* A successful command means firmware recognizes + * VIC_FEATURE_SRIOV; supported_versions is available + * for sub-feature versioning in the future. + */ + err =3D vnic_dev_get_supported_feature_ver(enic->vdev, + VIC_FEATURE_SRIOV, + &supported_versions, + &a1); + if (err) { + dev_warn(&pdev->dev, + "SR-IOV V2 not supported by current firmware. Upgrade to VIC FW 5.3(4.= 72) or higher.\n"); + enic->vf_type =3D ENIC_VF_TYPE_NONE; + } } #endif =20 diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/et= hernet/cisco/enic/vnic_devcmd.h index 605ef17f967e..7a4bce736105 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h +++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h @@ -734,6 +734,8 @@ enum vic_feature_t { VIC_FEATURE_VXLAN, VIC_FEATURE_RDMA, VIC_FEATURE_VXLAN_PATCH, + VIC_FEATURE_PTP, + VIC_FEATURE_SRIOV, VIC_FEATURE_MAX, }; =20 --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-1.cisco.com (alln-iport-1.cisco.com [173.37.142.88]) (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 AE3A34C6EF3; Wed, 13 May 2026 15:16:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.88 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685370; cv=none; b=mTa/4tVB7CWVD8eqokdSu3AquxAVpcFCbkCcyVoFfk5ix+CrDij1TRdd0tg8CGS50H4x5O5qmMr/hmurgVoNMcv6tKwzJ6QGMEgtkcugf+L80dYi78t4Vu4IqEB//JEXa3YET421g/BJoFK2GjM/zmNvYhYYlYNzHGtS7N6flm4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685370; c=relaxed/simple; bh=rahtvEHjyG03MHv75pkt847hFSWGTg6b86WsY5tEoN4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fENBHZA5G0i4z3PKNq3xg4NY549EnP2fGNQ69tO8UkSJnvLiqW3qkx8uc4oYnQgDfSMZymvTwaIQIV584TKpC2i8Uik2FikXHktYXmfmjmIH1KpqjMQwG60nYhiwlbrWsMQdaVnFPwZ9wvGJFKqxyv9t0FVH3ZW7+Y8MHWNri1o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=XnEvNzFC; arc=none smtp.client-ip=173.37.142.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="XnEvNzFC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=10537; q=dns/txt; s=iport01; t=1778685368; x=1779894968; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=nNzaRjGD90Dx0TuiJhJgbREnHiKYrYEuLUFfOl2vkXM=; b=XnEvNzFCwtQUv2m+Oqa3CM7nidm0UTqrw+CImZTEovdkHEWuF4Yi5QM+ US900nQWy+5sIVp+TS9l4B1pLA996Uo/O29aE7tokJlkvE+FebXbdDN6h dbaPqcMT9O5sOREDSNN1+OKloxEfW0bsHCOgiIofFkL8SpxSuiuGxDMPm ayo08m41josOHkEgVLLd0mLM27WhuTgVg49xChgARVWfw4spjCPK3TapF TnC6KYUuTXx+66nqMHGbgPT33W8jplUSiiyLB7qWvfhgl1iXWKBB0G849 mI9HW1D0UqcEgkOaVThZ4/GZkLZ+rhQMQCNwy9427fB4JcRR0BTJmSoAT A==; X-CSE-ConnectionGUID: 8IzwCOh4Qh+IHqWf2XRmAg== X-CSE-MsgGUID: GIxp4UGuTSmmwWOPEMFbWQ== X-IPAS-Result: =?us-ascii?q?A0BFAgCnlARq/5D/Ja1aHgEBCxIMggULgleBUENJhFePU?= =?us-ascii?q?4Ihnh0UgWsPAQEBD1EEAQGFBgKNMgImNAkOAQIEAwIDAQEBAQEBAQEBAQELA?= =?us-ascii?q?QEFAQEBAgEHBYEOE4ZchlsCAQMjBFIQJQImAgJGEAYBEoMCgnQDswx6fzOBA?= =?us-ascii?q?YR92USBZAELFAGBCi6FcoJnAYFwhAY7hEAnG4FJRIEUAYNohAUBBBWDf4JpB?= =?us-ascii?q?IMcFIF7jH0JP4ECHANZLAFVEw0KCwcFYVIzAyAKCxISGBUCFC8PBBYyHXAMJ?= =?us-ascii?q?xIsFzNYGwcFgUuCBXIUMQQhgQKEX3gjLANOgUMDCxgNSBEsNwYOGwQ9AW4Hi?= =?us-ascii?q?j8dD4EoF3FZNQFNb4EhHCySYAiDdo1da4E1n1mEJoFkoA4BMpdmkwWZBiKjS?= =?us-ascii?q?W6EaIFoPIFZMxoIGxWDIlMZD44qAxbMOycyPQEBBwIHDQMLgWiQABEXgVUBA?= =?us-ascii?q?Q?= IronPort-Data: A9a23:glWXraDvDyz2rBVW/+niw5YqxClBgxIJ4kV8jS/XYbTApGkghWYCz WpKCzrSaareNjGmetknOY6yoEhV68DXmNNhOVdlrnsFo1CmBibm6XV1Cm+qYkt+++WaFBoPA /02M4eGdIZvCCeA+n9BC5C5xVFkz6aEW7HgP+DNPyF1VGdMRTwo4f5Zs7ZRbrVA357jWGthh fuo+5eBYAL8gGYtWo4pw/vrRC1H7ayaVAww5jTSVdgT1HfCmn8cCo4oJK3ZBxPQXolOE+emc P3Ixbe/83mx109F5gSNy+uTnuUiG9Y+DCDW4pZkc/HKbitq+kTe5p0G2M80Mi+7vdkmc+dZk 72hvbToIesg0zaldO41C3G0GAkmVUFKFSOuzXWX6aSuI0P6n3TEk9R8E2oRPdEh+qVWIXhx+ 6YoEjUkYUXW7w626OrTpuhEnM8vKozveYgYoHwllW6fBvc9SpeFSKLPjTNa9G5v3YYVQrCEO pdfMGYzBPjDS0Un1lM/E5sinfyohXnXeDxDo1XTrq0yi4TW5FMtjeCyYYaJIrRmQ+16v1aA+ l/p4ljCBxQFC/un5B+r+E2V07qncSTTHdh6+KeD3vJjnlCW7mAaFhATUVy1vb+/h1LWc99TN kkd6Ccyhac180OvQ5/2WBjQiH2ZtBc0WNdKFeA+rgaXxcL86gCVHGUbDThMdNArqucyWDosk FSJ9/vxDDZitry9U3+R9r6I6zi1PEA9KW4EeD9BTgYf5dTniJ88gwiJTdt5FqOxyNrvFlnYx T2WoCUgr6scgNRN1Kih+13DxTW2qfD0ohUd/A7bWCehqwh+foPgP9Pu4lnA5vEGJ4GcJrWcg EU5dwGlxLhmJfmweOalGY3hwJnBCy65DQDh IronPort-HdrOrdr: A9a23:gVBHJ629gnPbRHJcyarwDQqjBEQkLtp133Aq2lEZdPWaSL39qy nIppUmPH7P5gr5N0tMpTntAsO9qDbnhPxICOoqUotKIjOHhILAFugLhrcKgQeQeBEWndQw6U 4PSdkaNPTASXV3ksr+5hC1CJIDzMnvytHQuc7ui1pgUg1ubbht9ENCCgidGlBrXwUuP+teKH Pl3LshmxOQPVIKc8+8Gn4JG8LHp9HNidbaRCRuPW9e1OFL5gnYkoIT1HOjr2wjbw8= X-Talos-CUID: =?us-ascii?q?9a23=3A7QrvqmqIEA5V9rzYTs4r9gfmUZAEYGL263eMGk/?= =?us-ascii?q?7KEZwd7PPeWWV0awxxg=3D=3D?= X-Talos-MUID: =?us-ascii?q?9a23=3A9I5HYw4qt+g5xiaIi0iXNeg0xoxHwrS2VH0ijKk?= =?us-ascii?q?9vsybCgtIFhKzhguOF9o=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="745079440" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-1.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:02 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id B00821800048F; Wed, 13 May 2026 15:16:01 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:39 -0700 Subject: [PATCH net-next v7 02/10] enic: add admin channel open and close for SR-IOV 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-2-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=10910; i=satishkh@cisco.com; h=from:subject:message-id; bh=rahtvEHjyG03MHv75pkt847hFSWGTg6b86WsY5tEoN4=; b=ME8rQ2c+srl9V1pEoTWkLaQ00kbO0oYK0uThDp+/BSgI8ORbc8vb1AIqX8MN1F8X+mbHgnJzK oIZq0SjQSfOCANOGFqMcdLI71WXtsik1fr4wEigDs7XYLHIS8nxBzc6 X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com The V2 SR-IOV design uses a dedicated admin channel (WQ/RQ/CQ/INTR on separate BAR resources) for PF-VF mailbox communication rather than firmware-proxied devcmds. Introduce enic_admin_channel_open() and enic_admin_channel_close(). Open allocates and initialises the admin WQ, RQ, and two CQs (one per direction), then issues CMD_QP_TYPE_SET to tell firmware the queues are admin-type. Close reverses the sequence. enic_admin_wq_buf_clean() unmaps and frees any WQ buffers still held at close time, fixing a DMA mapping leak when a send times out. Add CMD_QP_TYPE_SET (97), QP_TYPE_ADMIN/DATA, and QP_ENABLE/QP_DISABLE defines to vnic_devcmd.h. Add VNIC_CQ_* named constants to vnic_cq.h so CQ initialisation parameters are self-documenting from their first introduction. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/Makefile | 3 +- drivers/net/ethernet/cisco/enic/enic_admin.c | 216 ++++++++++++++++++++++= ++++ drivers/net/ethernet/cisco/enic/enic_admin.h | 15 ++ drivers/net/ethernet/cisco/enic/vnic_cq.h | 9 ++ drivers/net/ethernet/cisco/enic/vnic_devcmd.h | 11 ++ 5 files changed, 253 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/etherne= t/cisco/enic/Makefile index a96b8332e6e2..7ae72fefc99a 100644 --- a/drivers/net/ethernet/cisco/enic/Makefile +++ b/drivers/net/ethernet/cisco/enic/Makefile @@ -3,5 +3,6 @@ obj-$(CONFIG_ENIC) :=3D enic.o =20 enic-y :=3D enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \ - enic_ethtool.o enic_api.o enic_clsf.o enic_rq.o enic_wq.o + enic_ethtool.o enic_api.o enic_clsf.o enic_rq.o enic_wq.o \ + enic_admin.o =20 diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.c b/drivers/net/eth= ernet/cisco/enic/enic_admin.c new file mode 100644 index 000000000000..aa21868a9209 --- /dev/null +++ b/drivers/net/ethernet/cisco/enic/enic_admin.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright 2025 Cisco Systems, Inc. All rights reserved. + +#include +#include + +#include "vnic_dev.h" +#include "vnic_wq.h" +#include "vnic_rq.h" +#include "vnic_cq.h" +#include "vnic_intr.h" +#include "vnic_resource.h" +#include "vnic_devcmd.h" +#include "enic.h" +#include "enic_admin.h" +#include "cq_desc.h" +#include "wq_enet_desc.h" +#include "rq_enet_desc.h" + +/* Clean up any admin WQ buffers still held by hardware at close time. + * Normally buffers are freed inline after send completion, but a timed-out + * send intentionally leaves the buffer live until the queue is stopped. + */ +static void enic_admin_wq_buf_clean(struct vnic_wq *wq, + struct vnic_wq_buf *buf) +{ + struct enic *enic =3D vnic_dev_priv(wq->vdev); + + if (buf->os_buf) { + dma_unmap_single(&enic->pdev->dev, buf->dma_addr, + buf->len, DMA_TO_DEVICE); + kfree(buf->os_buf); + buf->os_buf =3D NULL; + } +} + +/* No-op: admin RQ buffer teardown is handled in enic_admin_channel_close = */ +static void enic_admin_rq_buf_clean(struct vnic_rq *rq, + struct vnic_rq_buf *buf) +{ +} + +static int enic_admin_qp_type_set(struct enic *enic, u32 enable) +{ + u64 a0 =3D QP_TYPE_ADMIN, a1 =3D enable; + int wait =3D 1000; + int err; + + spin_lock_bh(&enic->devcmd_lock); + err =3D vnic_dev_cmd(enic->vdev, CMD_QP_TYPE_SET, &a0, &a1, wait); + spin_unlock_bh(&enic->devcmd_lock); + + return err; +} + +static int enic_admin_alloc_resources(struct enic *enic) +{ + int err; + + err =3D vnic_wq_alloc_with_type(enic->vdev, &enic->admin_wq, 0, + ENIC_ADMIN_DESC_COUNT, + sizeof(struct wq_enet_desc), + RES_TYPE_ADMIN_WQ); + if (err) + return err; + + err =3D vnic_rq_alloc_with_type(enic->vdev, &enic->admin_rq, 0, + ENIC_ADMIN_DESC_COUNT, + sizeof(struct rq_enet_desc), + RES_TYPE_ADMIN_RQ); + if (err) + goto free_wq; + + /* admin_cq[0] is the WQ completion queue. WQ CQEs are always + * 16 bytes wide; firmware always writes 16-byte CQEs for WQ + * completions on every WQ, including the admin channel WQ. + * Use sizeof(struct cq_desc) accordingly. + */ + err =3D vnic_cq_alloc_with_type(enic->vdev, &enic->admin_cq[0], 0, + ENIC_ADMIN_DESC_COUNT, + sizeof(struct cq_desc), + RES_TYPE_ADMIN_CQ); + if (err) + goto free_rq; + + /* admin_cq[1] is the RQ completion queue. Its descriptor size + * must match what firmware writes. enic_ext_cq() called earlier + * in probe issues CMD_CQ_ENTRY_SIZE_SET for VNIC_RQ_ALL, + * programming firmware to write CQ entries of (16 << enic->ext_cq) + * bytes for every RQ CQ on the vNIC, including the admin RQ CQ. + * Allocating with the same size keeps the host poller and + * firmware in lockstep: + * + * - The color/valid bit lives at byte (desc_size - 1) of every + * cq_enet_rq_desc[_32|_64] variant, so enic_admin_cq_color() + * reads it from the correct offset. + * - Only the first 15 bytes of the descriptor (vlan, + * bytes_written_flags, ...) are accessed by the admin path; + * these fields are identical across all three variants (see + * comment in enic_rq.c above cq_enet_rq_desc_dec()). + */ + err =3D vnic_cq_alloc_with_type(enic->vdev, &enic->admin_cq[1], 1, + ENIC_ADMIN_DESC_COUNT, + 16 << enic->ext_cq, + RES_TYPE_ADMIN_CQ); + if (err) + goto free_cq0; + + return 0; + +free_cq0: + vnic_cq_free(&enic->admin_cq[0]); +free_rq: + vnic_rq_free(&enic->admin_rq); +free_wq: + vnic_wq_free(&enic->admin_wq); + return err; +} + +static void enic_admin_free_resources(struct enic *enic) +{ + vnic_cq_free(&enic->admin_cq[1]); + vnic_cq_free(&enic->admin_cq[0]); + vnic_rq_free(&enic->admin_rq); + vnic_wq_free(&enic->admin_wq); +} + +static void enic_admin_init_resources(struct enic *enic) +{ + vnic_wq_init(&enic->admin_wq, + 0, 0, 0); /* cq_index, err_intr_enable, err_intr_offset */ + vnic_rq_init(&enic->admin_rq, + 1, 0, 0); /* cq_index, err_intr_enable, err_intr_offset */ + vnic_cq_init(&enic->admin_cq[0], + VNIC_CQ_FC_DISABLE, + VNIC_CQ_COLOR_ENABLE, + 0, 0, 1, /* cq_head, cq_tail, cq_tail_color */ + VNIC_CQ_INTR_DISABLE, + VNIC_CQ_ENTRY_ENABLE, + VNIC_CQ_MSG_DISABLE, + 0, /* interrupt_offset */ + 0 /* cq_message_addr */); + vnic_cq_init(&enic->admin_cq[1], + VNIC_CQ_FC_DISABLE, + VNIC_CQ_COLOR_ENABLE, + 0, 0, 1, /* cq_head, cq_tail, cq_tail_color */ + VNIC_CQ_INTR_DISABLE, + VNIC_CQ_ENTRY_ENABLE, + VNIC_CQ_MSG_DISABLE, + 0, /* interrupt_offset */ + 0 /* cq_message_addr */); +} + +int enic_admin_channel_open(struct enic *enic) +{ + int err; + + if (!enic->has_admin_channel) + return -ENODEV; + + err =3D enic_admin_alloc_resources(enic); + if (err) { + netdev_err(enic->netdev, + "Failed to alloc admin channel resources: %d\n", + err); + return err; + } + + enic_admin_init_resources(enic); + + vnic_wq_enable(&enic->admin_wq); + vnic_rq_enable(&enic->admin_rq); + + err =3D enic_admin_qp_type_set(enic, QP_ENABLE); + if (err) { + netdev_err(enic->netdev, + "Failed to set admin QP type: %d\n", err); + goto disable_queues; + } + + return 0; + +disable_queues: + enic_admin_qp_type_set(enic, QP_DISABLE); + if (vnic_wq_disable(&enic->admin_wq)) + netdev_warn(enic->netdev, "Failed to disable admin WQ\n"); + if (vnic_rq_disable(&enic->admin_rq)) + netdev_warn(enic->netdev, "Failed to disable admin RQ\n"); + enic_admin_free_resources(enic); + return err; +} + +void enic_admin_channel_close(struct enic *enic) +{ + int err; + + if (!enic->has_admin_channel) + return; + + enic_admin_qp_type_set(enic, QP_DISABLE); + + err =3D vnic_wq_disable(&enic->admin_wq); + if (err) + netdev_warn(enic->netdev, + "Failed to disable admin WQ: %d\n", err); + err =3D vnic_rq_disable(&enic->admin_rq); + if (err) + netdev_warn(enic->netdev, + "Failed to disable admin RQ: %d\n", err); + + vnic_wq_clean(&enic->admin_wq, enic_admin_wq_buf_clean); + vnic_rq_clean(&enic->admin_rq, enic_admin_rq_buf_clean); + vnic_cq_clean(&enic->admin_cq[0]); + vnic_cq_clean(&enic->admin_cq[1]); + enic_admin_free_resources(enic); +} diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.h b/drivers/net/eth= ernet/cisco/enic/enic_admin.h new file mode 100644 index 000000000000..569aadeb9312 --- /dev/null +++ b/drivers/net/ethernet/cisco/enic/enic_admin.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright 2025 Cisco Systems, Inc. All rights reserved. */ + +#ifndef _ENIC_ADMIN_H_ +#define _ENIC_ADMIN_H_ + +#define ENIC_ADMIN_DESC_COUNT 64 +#define ENIC_ADMIN_BUF_SIZE 2048 + +struct enic; + +int enic_admin_channel_open(struct enic *enic); +void enic_admin_channel_close(struct enic *enic); + +#endif /* _ENIC_ADMIN_H_ */ diff --git a/drivers/net/ethernet/cisco/enic/vnic_cq.h b/drivers/net/ethern= et/cisco/enic/vnic_cq.h index d46d4d2ef6bb..35ffa3230713 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_cq.h +++ b/drivers/net/ethernet/cisco/enic/vnic_cq.h @@ -76,6 +76,15 @@ int vnic_cq_alloc(struct vnic_dev *vdev, struct vnic_cq = *cq, unsigned int index, int vnic_cq_alloc_with_type(struct vnic_dev *vdev, struct vnic_cq *cq, unsigned int index, unsigned int desc_count, unsigned int desc_size, unsigned int res_type); +#define VNIC_CQ_FC_ENABLE 1 +#define VNIC_CQ_FC_DISABLE 0 +#define VNIC_CQ_COLOR_ENABLE 1 +#define VNIC_CQ_INTR_ENABLE 1 +#define VNIC_CQ_INTR_DISABLE 0 +#define VNIC_CQ_ENTRY_ENABLE 1 +#define VNIC_CQ_MSG_ENABLE 1 +#define VNIC_CQ_MSG_DISABLE 0 + void vnic_cq_init(struct vnic_cq *cq, unsigned int flow_control_enable, unsigned int color_enable, unsigned int cq_head, unsigned int cq_tail, unsigned int cq_tail_color, unsigned int interrupt_enable, diff --git a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h b/drivers/net/et= hernet/cisco/enic/vnic_devcmd.h index 7a4bce736105..47b3f1c754cf 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_devcmd.h +++ b/drivers/net/ethernet/cisco/enic/vnic_devcmd.h @@ -455,8 +455,19 @@ enum vnic_devcmd_cmd { */ CMD_CQ_ENTRY_SIZE_SET =3D _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 90), =20 + /* + * Set queue pair type (admin or data) + * in: (u32) a0 =3D queue pair type (0 =3D admin, 1 =3D data) + * in: (u32) a1 =3D enable (1) / disable (0) + */ + CMD_QP_TYPE_SET =3D _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ENET, 97), }; =20 +#define QP_TYPE_ADMIN 0 +#define QP_TYPE_DATA 1 +#define QP_ENABLE 1 +#define QP_DISABLE 0 + /* CMD_ENABLE2 flags */ #define CMD_ENABLE2_STANDBY 0x0 #define CMD_ENABLE2_ACTIVE 0x1 --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-1.cisco.com (alln-iport-1.cisco.com [173.37.142.88]) (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 E45AE4C6F0D; Wed, 13 May 2026 15:16:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.88 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685372; cv=none; b=D6k6X8cjv7a8rdEUu6ia2NgiYbxBaPKZ3JXoA9ywbpztU8b/NZPxc96H53S0YhZvEOHQkTlvG0oyhTzcpUHqwvCTxuq6qC3LlcNPhLtzNuRAASDh1XLVvhkwax+Ju8QV0F3mGla/Q686cpOaM6yRi/nS/ZyoUF9/LZVS2PeRCmQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685372; c=relaxed/simple; bh=ZPi9K+smQv5qTQqT85z/NyNntS9Rwouv0nOUJ93vmiY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rGnWxkHptC1fJPddDGOwVc/EROkp3wRRI1XPQJTv6PoAxH36hMnbAJA6EqpKTDpRYtlWsCuD+FxYEEXOrsnH+AgWbTxxRlH0a8b/N+3AXHLkO7mxOlHkatO+BsuauXVKURIANiawIOPQ3Hw4uvYYXGUH6TNTM6oraN+W+8hwM4c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=DwsPWLH/; arc=none smtp.client-ip=173.37.142.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="DwsPWLH/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=3813; q=dns/txt; s=iport01; t=1778685371; x=1779894971; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=kns4Mab/JliJKmkozoUpqJaxGVnLf8P8NwQOX4HNIqo=; b=DwsPWLH/yfC9CDKUql22RlvTaQx8OuuTnVt7MIUldUZ4j2yqH6KZoJc/ xyfVAp+hOocCRSPXKDxPggGeQxqNrgLU5ZiEwkAdavt8DBHGk5s6/9rcC +YL9Sm8t3gqVZwNpz8JOE2pGZgYttXOzsFswuaf3lw1+a9JiDx/CPvdJ7 uGiNmYhQxSTBGCNOsCiFFaFawJ6hgBNgDUtTgRzEpD5pIyyWI6B4jBZmC F9vXN9oTS8cmi9TznnA13X0Ayj/rC97HpNOOxUozkqpKBlAH6Cyr7RwzA sseIcYjxc2FdK0w4bvKAgI9eN+slWIAertnLQhhnb2bzTkjMK1XelLLAB Q==; X-CSE-ConnectionGUID: mBIVidjRTMKE429n5hHE0Q== X-CSE-MsgGUID: oPjuaCpgSY+ii/53IZpEEg== X-IPAS-Result: =?us-ascii?q?A0BFAgCnlARq/5D/Ja1aHgEBCxIMggULgleBUENJhFePU?= =?us-ascii?q?4Ihnh2Bfw8BAQEPUQQBAYUGAo0yAiY0CQ4BAgQDAgMBAQEBAQEBAQEBAQsBA?= =?us-ascii?q?QUBAQECAQcFgQ4ThlyGWwIBAyMEUhAlAiYCAkYQBgESgwKCdAOzDHp/M4EBh?= =?us-ascii?q?H3ZRIFkAQsUAYEKLoVygmcBgXCEBjuEQCcbgUlEgRWDaIEZgwaDf4JpBIMcF?= =?us-ascii?q?I54CT+BAhwDWSwBVRMNCgsHBWFSMwMgCgsSEhgVAhQvDwQWMh1wDCcSLBczW?= =?us-ascii?q?BsHBYFLggVyFDEEIYEChF94IywDToFDAwsYDUgRLDcGDhsEPQFuB4o/HQ+BP?= =?us-ascii?q?3FZNRSBKSM0k3IIFYNhjV1rgTWfWYQmgWSgDgEyl2aTBZkGIqQ3hGiBaDyBW?= =?us-ascii?q?TMaCBsVgyJTGQ+OKgMWzDsnMj8HAgcOApIEgWwBAQ?= IronPort-Data: A9a23:jDNKS6lsSPESA72/SBrBtPfo5gxBJ0RdPkR7XQ2eYbSJt1+Wr1Gzt xIbD2iGOvyOY2b1eo9waYTnp0JVucPRm9dhSwJopXxjF1tH+JHPbTi7wugcHM8zwunrFh8PA xA2M4GYRCwMZiaC4E/raf658SUUOZigHtLUEPTDNj16WThqQSIgjQMLs+Mii+aEu/Dha++2k Y20+Za31GONgWYubDpJsvnb8XuDgdyr0N8mlg1mDRx0lAe2e0k9VPo3Oay3Jn3kdYhYdsbSb /rD1ryw4lTC9B4rDN6/+p6jGqHdauePVeQmoiM+t5mK2nCulARrukoIHKZ0hXNsttm8t4sZJ OOhGnCHYVxB0qXkwIzxWvTDes10FfUuFLTveRBTvSEPpqHLWyOE/hlgMK05FYgy29h2DWN0y dk7BWxXPxbeh8KbmIvuH4GAhux7RCXqFJkUtnclyXTSCuwrBMicBa7L/tRfmjw3g6iiH96HO JFfMmUpNkmdJUQTZj/7C7pm9AusrmL2bzxDqFGVjaE2+GPUigd21dABNfKKJoHSGpQJwhfwS mTu+Fz7HxgxLNOk+HmE8zXx3c79hQ7WV9dHfFG/3rsw6LGJ/UQfAQMbUHO3qOe0j0q5Vc4ZL UEIkgIjobU3/V6mUvHyWBq3pHPCtRkZM/JTDuczwAKA0KzZ50CeHGdsZjdHZMYrq4wwSCAm2 0Ghm87vA3pksNW9UXuX+7GVhSm/NSgcMSkJYipsZQ8E5cTz5YI+lBTCSv59H6OvyN74Azf9x 3aNtidWr7MekcIGyY2l8l3dxTGhvJ7ESkgy/Aq/Y46+xhlyaIjgY8mj7kLWqK4fao2YVVKG+ nMDnqBy8dwzMH1ErwTVKM1lIV1jz6/t3OH06bK3I6Qcyg== IronPort-HdrOrdr: A9a23:MaMnWai/QujXMdVVZ3aedVIl0XBQXiwji2hC6mlwRA09TyVXrb HLoB19737JYVcqNk3I9ursBEDtexnhHNtOkOss1NSZMzUOxlHJEGgK1+KLqAEIWReOldK1vp 0NT0ERMqyUMXFKyev3/wW8Fc8t252k/LDAv5am815dCSxndK1k6R50EUKgEkNwTBRbHpZRLu v72iM+nUvGRV0nKuKmG3ICQ+/P4/fPlJ7gfFo6IiRP0nj3sdttg4SKaSRxGXwlIkhy/Ys= X-Talos-CUID: =?us-ascii?q?9a23=3AGqpPBWpQTA9USgvHnJAmvEjmUcUPU0PcwHXqH2q?= =?us-ascii?q?bJDozGbvISX+9oJoxxg=3D=3D?= X-Talos-MUID: =?us-ascii?q?9a23=3AQvYbIwx9W8Z0h1AyENY9wFaj142aqKOWCl0Euo0?= =?us-ascii?q?JgPjHNC03Zmy8viyab4Byfw=3D=3D?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="745079449" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-1.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:03 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id 6D7E9180004A6; Wed, 13 May 2026 15:16:02 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:40 -0700 Subject: [PATCH net-next v7 03/10] enic: add admin RQ buffer management 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-3-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=3879; i=satishkh@cisco.com; h=from:subject:message-id; bh=ZPi9K+smQv5qTQqT85z/NyNntS9Rwouv0nOUJ93vmiY=; b=1bmgFrhSXPiocbM2hQP52g4tXLjFFYL7ksd3FFxcHr/9fdlo8pLKmZyYfZtdfpjLk4Pk6lU1t os9WsvLRJm4DGGOhidTQsqfvhrms4jvVt7fvKLL3t0LUL84H/BkaU+W X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com The admin receive queue needs pre-posted DMA buffers for incoming mailbox messages from VFs. Each buffer is a kmalloc'd region mapped for DMA (2048 bytes, sufficient for any MBOX message). Add enic_admin_rq_fill(gfp) to post buffers at open time, and enic_admin_rq_drain() to unmap and free them at close time. Wire both into the admin channel open/close paths. The gfp_t parameter allows GFP_KERNEL at open time and GFP_ATOMIC when refilling from NAPI context (added in the next patch). Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic_admin.c | 66 ++++++++++++++++++++++++= +++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.c b/drivers/net/eth= ernet/cisco/enic/enic_admin.c index aa21868a9209..b28fc6c656cc 100644 --- a/drivers/net/ethernet/cisco/enic/enic_admin.c +++ b/drivers/net/ethernet/cisco/enic/enic_admin.c @@ -3,6 +3,7 @@ =20 #include #include +#include =20 #include "vnic_dev.h" #include "vnic_wq.h" @@ -34,10 +35,63 @@ static void enic_admin_wq_buf_clean(struct vnic_wq *wq, } } =20 -/* No-op: admin RQ buffer teardown is handled in enic_admin_channel_close = */ static void enic_admin_rq_buf_clean(struct vnic_rq *rq, struct vnic_rq_buf *buf) { + struct enic *enic =3D vnic_dev_priv(rq->vdev); + + if (!buf->os_buf) + return; + + dma_unmap_single(&enic->pdev->dev, buf->dma_addr, buf->len, + DMA_FROM_DEVICE); + kfree(buf->os_buf); + buf->os_buf =3D NULL; +} + +static int enic_admin_rq_post_one(struct enic *enic, gfp_t gfp) +{ + struct vnic_rq *rq =3D &enic->admin_rq; + struct rq_enet_desc *desc; + dma_addr_t dma_addr; + void *buf; + + buf =3D kmalloc(ENIC_ADMIN_BUF_SIZE, gfp); + if (!buf) + return -ENOMEM; + + dma_addr =3D dma_map_single(&enic->pdev->dev, buf, ENIC_ADMIN_BUF_SIZE, + DMA_FROM_DEVICE); + if (dma_mapping_error(&enic->pdev->dev, dma_addr)) { + kfree(buf); + return -ENOMEM; + } + + desc =3D vnic_rq_next_desc(rq); + rq_enet_desc_enc(desc, (u64)dma_addr | VNIC_PADDR_TARGET, + RQ_ENET_TYPE_ONLY_SOP, ENIC_ADMIN_BUF_SIZE); + vnic_rq_post(rq, buf, 0, dma_addr, ENIC_ADMIN_BUF_SIZE, 0); + + return 0; +} + +static int enic_admin_rq_fill(struct enic *enic, gfp_t gfp) +{ + struct vnic_rq *rq =3D &enic->admin_rq; + int err; + + while (vnic_rq_desc_avail(rq) > 0) { + err =3D enic_admin_rq_post_one(enic, gfp); + if (err) + return err; + } + + return 0; +} + +static void enic_admin_rq_drain(struct enic *enic) +{ + vnic_rq_clean(&enic->admin_rq, enic_admin_rq_buf_clean); } =20 static int enic_admin_qp_type_set(struct enic *enic, u32 enable) @@ -171,6 +225,13 @@ int enic_admin_channel_open(struct enic *enic) vnic_wq_enable(&enic->admin_wq); vnic_rq_enable(&enic->admin_rq); =20 + err =3D enic_admin_rq_fill(enic, GFP_KERNEL); + if (err) { + netdev_err(enic->netdev, + "Failed to fill admin RQ buffers: %d\n", err); + goto disable_queues; + } + err =3D enic_admin_qp_type_set(enic, QP_ENABLE); if (err) { netdev_err(enic->netdev, @@ -186,6 +247,7 @@ int enic_admin_channel_open(struct enic *enic) netdev_warn(enic->netdev, "Failed to disable admin WQ\n"); if (vnic_rq_disable(&enic->admin_rq)) netdev_warn(enic->netdev, "Failed to disable admin RQ\n"); + enic_admin_rq_drain(enic); enic_admin_free_resources(enic); return err; } @@ -209,7 +271,7 @@ void enic_admin_channel_close(struct enic *enic) "Failed to disable admin RQ: %d\n", err); =20 vnic_wq_clean(&enic->admin_wq, enic_admin_wq_buf_clean); - vnic_rq_clean(&enic->admin_rq, enic_admin_rq_buf_clean); + enic_admin_rq_drain(enic); vnic_cq_clean(&enic->admin_cq[0]); vnic_cq_clean(&enic->admin_cq[1]); enic_admin_free_resources(enic); --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-1.cisco.com (alln-iport-1.cisco.com [173.37.142.88]) (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 836364C77A5; Wed, 13 May 2026 15:16:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.88 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685373; cv=none; b=VFFlmSKnPLV7phGX/97PO/kW4bgTFqp2gnRltorsKBXZk+0sswFTn0w9KJP4BJYCdfX5G/7uEIY7i/T7hINLWZ534MNCg6Db4G1sARbcbmnYvBC3EVJvGapup6BcrpNIWum9x5EsYdQ8ELudMGDVx72KLniZ974UCZhgisFap24= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685373; c=relaxed/simple; bh=m9ORrJ/+23FHsn3EZVUdPqmZnO3NCYGuv8JL/0lr/Gw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gQ9L5ylkCx+Pka+CueLZmEnLTP6QdxWiJ2pp6ffHi3oJ8VauUwYvlVMK26WDzSkLlIxyBSMR9O5NvAT0exa9WtEqAAZTjn4hY6N+jmqgP6ev6Dj15InTY5dFHcE6r02WkRDUyYi/9FHbeZDWHzCHA1ZYzw+L7tR+wggN+OD2zJ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=DYDe4Z0p; arc=none smtp.client-ip=173.37.142.88 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="DYDe4Z0p" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=14598; q=dns/txt; s=iport01; t=1778685371; x=1779894971; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=9a7KD6izkEAOndFZkJtEMkYeO4Jdp4t5i1BthxLNU1c=; b=DYDe4Z0p071nM53q7Yl6GT9iXfcIfW/vqhVbK9EYtbP/xvpKAhMxXI3c HOAQcYc+ScuDrs9yls95Ff9MKwPY40iTGunOrOoXRFkUZBzUW6ZWlw5NM P8/zhMVpFUxC7Ho3tU9hrrfxC9KuQb52yuwrDQmSrooBXp9p+hd/vIjQ2 WDcD0MsipJkZ2J2lNfkE/0WMxgOunFaFbKEzIIdcN6KjdJ+bSU5NqsMsy fXQT938jK58gTQ3lA0SwdxC0Kp8I0xtrU65VKRBG6DvpX6osqYg0QetwU 1rl85lNP6wCyS70MfY5XeJWpCLweMUx9WM9sJDVNGoZbkchfCZidsn86v g==; X-CSE-ConnectionGUID: +iqbNErOQmSLinqHtdF0vw== X-CSE-MsgGUID: JCV8Evt5S6StiOhH00qT4Q== X-IPAS-Result: =?us-ascii?q?A0ADAACnlARq/5D/Ja1aGgEBAQEBAQEBAQEDAQEBARIBA?= =?us-ascii?q?QEBAgIBAQEBgXwFAQEBAQsBglaBUENJhFeIHIc3giGRTYxQgX8PAQEBD1EEA?= =?us-ascii?q?QGFBgKNMgImNAkOAQIEAwIDAQEBAQEBAQEBAQELAQEFAQEBAgEHBYEOE4Zch?= =?us-ascii?q?lsCAQMjBFIQJQImAgJGEAYBEoMCgnQDswx6fzOBAYR92USBZAELFAGBCi4Bh?= =?us-ascii?q?XGCZwGBcIQGO4RAJxuBSUSBFAGDaIQahASCaQSCInoUhWeBAIgRCT+BAhwDW?= =?us-ascii?q?SwBVRMNCgsHBWFSMwMgCgsSEhgVAhQvDwQWMh1wDCcSLBczWBsHBYFLggVyF?= =?us-ascii?q?DEEIYEChF94IywDToFDAwsYDUgRLDcGDhsEPQFuB4o/HQ+BP3EBWAEaBxR6N?= =?us-ascii?q?gw8CBMdFBkcKZJjGwKDYYwngTZrgTWfWYQmgWSgDgEyhASTYjOSUpkGIqMzN?= =?us-ascii?q?AEYN4RogWg8gVkzGggbFTuCZ1MZD44qAxYczB8nMj0CBwIHDQMLkWgEgXkBA?= =?us-ascii?q?Q?= IronPort-Data: A9a23:wquNoqOyp07j1GjvrR1llsFynXyQoLVcMsEvi/4bfWQNrUongmFRz GMYCjrQOqvYYTT3eNB/a97loEkAscDQxoNlG3M5pCpnJ55oRWUpJjg4wmPYZX76whjrFRo/h ykmQoCeaphyFTmE+kvF3oHJ9RFUzbuPSqf3FNnKMyVwQR4MYCo6gHqPocZh6mJTqYb/WVjlV e/a+ZWFZgf4gmUsawr41orawP9RlKWq0N8nlgRWicBj5Df2i3QTBZQDEqC9R1OQapVUBOOzW 9HYx7i/+G7Dlz91Yj9yuu+mGqGiaue60Tmm0hK6aYD76vRxjnBaPpIACRYpQRw/ZwNlMDxG4 I4lWZSYEW/FN0BX8QgXe0Ew/ypWZcWq9FJbSJSymZT78qHIT5fj67ZvFUsQEJc/w+NMJWBI7 NwEJB5VcA/W0opawJrjIgVtrt4oIM+uOMYUvWttiGmGS/0nWpvEBa7N4Le03h9p2ZsIRqmYP ZdEL2MzMHwsYDUXUrsTIIk3gOazhnr/WzZZs1mS46Ew5gA/ySQujOW1b4uJJ4DiqcN9vG2m9 k/Y4znCXCoGNfuf6WLd607wv7qa9c/8cMdIfFGizdZmiUOew0QfAQMbUF+8r+X/jEOiM/pSJ 1ER8zgjsYA980ukStS7VBq9yFaHoxQVc9ldCes37EeK0KW8yw+fCnIJUX1HZcAqudEeQSEs0 BmCn7vBHTVlvbuUYWiQ+redsXW5Pi19BWsDYzIUCAgI+d/upKktgR/VCNVuCqi4ipvyAz6Y6 zaHsCQzmZ0NgsMRkaa251bKh3SrvJehc+Iuzh/cUmTg6kZyY5SoItT3r1Pa9v1Hao2eSzFto UQ5piRX18hWZbnlqcBHaLxl8G2BjxpdDADhvA== IronPort-HdrOrdr: A9a23:QRFfna5jvv0kupBFVQPXwD7XdLJyesId70hD6qm+c20wTiX+ra GTdZUguyMc5wx9ZJhNo7q90ey7MBHhHP1OjrX5Q43DYOCOggLBR72Kr7GSoAEIcBeTygcy79 YET4FOTPD9ElR+i9/3+02bH8ZI+qj/zImYwcrT0HtpSxhncOVb7wl/AhuGCUEefnghOXNALu v62uN34xy9ZH8QcsO3QlMBX+TFupn3saiOW29/O/bigzP+9w9BL9XBYmOl4is= X-Talos-CUID: 9a23:s8iFFWFVc9I8Q79vqmIk9VcePO0/VUTY91PRJVaYFWpHEKOKHAo= X-Talos-MUID: 9a23:sYImUAXIHyxuYJDq/B3HumFPKts12PqVFEEqkbVe49C4aRUlbg== X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="745079454" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-1.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:03 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id 2B037180004BA; Wed, 13 May 2026 15:16:03 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:41 -0700 Subject: [PATCH net-next v7 04/10] enic: add admin CQ service with MSI-X interrupt and NAPI polling 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-4-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=15064; i=satishkh@cisco.com; h=from:subject:message-id; bh=m9ORrJ/+23FHsn3EZVUdPqmZnO3NCYGuv8JL/0lr/Gw=; b=2LeOpFEI0lHarlmDZZ0nA4DQ1h/RBIaPNwa+LuPy2jhCrTSIgjj3UpUU/dJIYjA6cdp69idBv RooWcR6GsxUCWvRxZ3URN0b4A96JtFtmGbUyADSrVMHt2HAI+PGr/rZ X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com Add completion queue service for the admin channel WQ and RQ, driven by an MSI-X interrupt and NAPI polling. The receive pipeline is: MSI-X ISR -> NAPI poll -> RQ CQ service -> message enqueue -> workqueue handler -> admin_rq_handler callback. NAPI drains the RQ CQ in softirq context, copying each received buffer into an enic_admin_msg and appending it to a spinlock-protected list. A system workqueue handler then processes each message in process context where sleeping (mutex, GFP_KERNEL allocations) is safe. The WQ CQ service counts transmit completions and is called from the synchronous MBOX send path. Interrupt generation is disabled on the WQ CQ (admin_cq[0]) because it is polled synchronously; only the RQ CQ (admin_cq[1]) is interrupt-driven via NAPI. The NAPI poll path refills admin RQ buffers with GFP_ATOMIC. Log a rate-limited warning when admin RQ buffer refill fails in NAPI context. The admin channel open/close paths set up and tear down the MSI-X interrupt, NAPI instance, and workqueue. CQ init enables interrupt delivery on the RQ CQ and sets the interrupt offset so completions trigger the admin ISR. The admin interrupt is allocated from the RES_TYPE_INTR_CTRL pool at index =3D=3D intr_count, the first slot beyond the data-path IRQs. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic.h | 8 + drivers/net/ethernet/cisco/enic/enic_admin.c | 303 +++++++++++++++++++++++= +++- drivers/net/ethernet/cisco/enic/enic_admin.h | 12 ++ 3 files changed, 319 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/= cisco/enic/enic.h index 08472420f3a1..1c09da3c0b1a 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -296,6 +296,14 @@ struct enic { struct vnic_rq admin_rq; struct vnic_cq admin_cq[2]; struct vnic_intr admin_intr; + struct napi_struct admin_napi; + unsigned int admin_intr_index; + struct work_struct admin_msg_work; + spinlock_t admin_msg_lock; /* protects admin_msg_list */ + struct list_head admin_msg_list; + u64 admin_msg_drop_cnt; + void (*admin_rq_handler)(struct enic *enic, void *buf, + unsigned int len); }; =20 static inline struct net_device *vnic_get_netdev(struct vnic_dev *vdev) diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.c b/drivers/net/eth= ernet/cisco/enic/enic_admin.c index b28fc6c656cc..9ebc69c7dda6 100644 --- a/drivers/net/ethernet/cisco/enic/enic_admin.c +++ b/drivers/net/ethernet/cisco/enic/enic_admin.c @@ -4,6 +4,7 @@ #include #include #include +#include =20 #include "vnic_dev.h" #include "vnic_wq.h" @@ -15,6 +16,7 @@ #include "enic.h" #include "enic_admin.h" #include "cq_desc.h" +#include "cq_enet_desc.h" #include "wq_enet_desc.h" #include "rq_enet_desc.h" =20 @@ -94,6 +96,248 @@ static void enic_admin_rq_drain(struct enic *enic) vnic_rq_clean(&enic->admin_rq, enic_admin_rq_buf_clean); } =20 +static unsigned int enic_admin_cq_color(void *cq_desc, unsigned int desc_s= ize) +{ + u8 type_color =3D *((u8 *)cq_desc + desc_size - 1); + + return (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK; +} + +unsigned int enic_admin_wq_cq_service(struct enic *enic) +{ + struct vnic_cq *cq =3D &enic->admin_cq[0]; + unsigned int work =3D 0; + void *desc; + + desc =3D vnic_cq_to_clean(cq); + while (enic_admin_cq_color(desc, cq->ring.desc_size) !=3D + cq->last_color) { + /* Ensure color bit is read before descriptor fields */ + rmb(); + vnic_cq_inc_to_clean(cq); + work++; + desc =3D vnic_cq_to_clean(cq); + } + + return work; +} + +static void enic_admin_msg_enqueue(struct enic *enic, void *buf, + unsigned int len) +{ + struct enic_admin_msg *msg; + + msg =3D kmalloc(struct_size(msg, data, len), GFP_ATOMIC); + if (!msg) { + enic->admin_msg_drop_cnt++; + return; + } + + msg->len =3D len; + memcpy(msg->data, buf, len); + + spin_lock(&enic->admin_msg_lock); + list_add_tail(&msg->list, &enic->admin_msg_list); + spin_unlock(&enic->admin_msg_lock); +} + +unsigned int enic_admin_rq_cq_service(struct enic *enic, unsigned int budg= et) +{ + struct vnic_cq *cq =3D &enic->admin_cq[1]; + struct vnic_rq *rq =3D &enic->admin_rq; + struct cq_enet_rq_desc *rq_desc; + struct vnic_rq_buf *buf; + u16 bwf, bytes_written; + unsigned int work =3D 0; + void *desc; + + desc =3D vnic_cq_to_clean(cq); + while (work < budget && + enic_admin_cq_color(desc, cq->ring.desc_size) !=3D + cq->last_color) { + /* Ensure CQ descriptor fields are read after + * the color/valid check. + */ + rmb(); + buf =3D rq->to_clean; + + /* Decode the actual number of bytes hardware wrote into + * the RX buffer. buf->len is the static allocation size + * (ENIC_ADMIN_BUF_SIZE) and would expose uninitialised + * heap memory beyond the real payload. bytes_written_flags + * is at the same offset in every cq_enet_rq_desc[_32|_64] + * variant. + */ + rq_desc =3D desc; + bwf =3D le16_to_cpu(rq_desc->bytes_written_flags); + bytes_written =3D bwf & CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK; + if (bytes_written > buf->len) + goto next_desc; + + dma_sync_single_for_cpu(&enic->pdev->dev, + buf->dma_addr, buf->len, + DMA_FROM_DEVICE); + + /* Drop on hardware error indications. Admin messages + * are internal to the VIC, not received over the wire. + * Firmware sets TRUNCATED when the message does not fit + * in the posted buffer, and FCS_OK is always set on + * healthy admin completions. + */ + if (bwf & CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) { + netdev_warn_once(enic->netdev, + "admin RQ: truncated message dropped\n"); + goto next_desc; + } + if (!(rq_desc->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK)) { + netdev_warn_once(enic->netdev, + "admin RQ: bad FCS, dropping message\n"); + goto next_desc; + } + + enic_admin_msg_enqueue(enic, buf->os_buf, bytes_written); + +next_desc: + enic_admin_rq_buf_clean(rq, rq->to_clean); + rq->to_clean =3D rq->to_clean->next; + rq->ring.desc_avail++; + + vnic_cq_inc_to_clean(cq); + work++; + desc =3D vnic_cq_to_clean(cq); + } + + if (enic_admin_rq_fill(enic, GFP_ATOMIC)) + work =3D budget; + + return work; +} + +static irqreturn_t enic_admin_isr_msix(int irq, void *data) +{ + struct napi_struct *napi =3D data; + + napi_schedule_irqoff(napi); + + return IRQ_HANDLED; +} + +static void enic_admin_msg_work_handler(struct work_struct *work) +{ + struct enic *enic =3D container_of(work, struct enic, admin_msg_work); + void (*handler)(struct enic *, void *, unsigned int); + struct enic_admin_msg *msg, *tmp; + LIST_HEAD(local_list); + + handler =3D READ_ONCE(enic->admin_rq_handler); + + spin_lock_bh(&enic->admin_msg_lock); + list_splice_init(&enic->admin_msg_list, &local_list); + spin_unlock_bh(&enic->admin_msg_lock); + + list_for_each_entry_safe(msg, tmp, &local_list, list) { + if (handler) + handler(enic, msg->data, msg->len); + list_del(&msg->list); + kfree(msg); + } +} + +static int enic_admin_napi_poll(struct napi_struct *napi, int budget) +{ + struct enic *enic =3D container_of(napi, struct enic, admin_napi); + unsigned int credits; + unsigned int rq_work; + + credits =3D vnic_intr_credits(&enic->admin_intr); + + rq_work =3D enic_admin_rq_cq_service(enic, budget); + + if (rq_work > 0) + schedule_work(&enic->admin_msg_work); + + if (rq_work < budget && napi_complete_done(napi, rq_work)) { + vnic_intr_return_credits(&enic->admin_intr, + credits ?: 1, + 1 /* unmask */, 0); + } else { + if (credits) + vnic_intr_return_credits(&enic->admin_intr, credits, + 0 /* don't unmask */, 0); + } + + return rq_work; +} + +static int enic_admin_setup_intr(struct enic *enic) +{ + unsigned int intr_index =3D enic->intr_count; + int err; + + if (vnic_dev_get_intr_mode(enic->vdev) !=3D VNIC_DEV_INTR_MODE_MSIX || + intr_index >=3D enic->intr_avail) + return -ENODEV; + + /* The admin INTR uses a slot in the same RES_TYPE_INTR_CTRL + * strided array of per-vector control blocks (mask, coalescing + * timer, credit return) that the data-path IRQs occupy in BAR0. + * vnic_intr_alloc() defaults to RES_TYPE_INTR_CTRL, which is what + * we want here. + */ + err =3D vnic_intr_alloc(enic->vdev, &enic->admin_intr, intr_index); + if (err) { + netdev_warn(enic->netdev, + "Failed to alloc admin intr at index %u: %d\n", + intr_index, err); + return err; + } + + enic->admin_intr_index =3D intr_index; + + snprintf(enic->msix[intr_index].devname, + sizeof(enic->msix[intr_index].devname), + "%s-admin", enic->netdev->name); + enic->msix[intr_index].isr =3D enic_admin_isr_msix; + enic->msix[intr_index].devid =3D &enic->admin_napi; + + netif_napi_add(enic->netdev, &enic->admin_napi, + enic_admin_napi_poll); + napi_enable(&enic->admin_napi); + + err =3D request_irq(enic->msix_entry[intr_index].vector, + enic->msix[intr_index].isr, 0, + enic->msix[intr_index].devname, + enic->msix[intr_index].devid); + if (err) { + netdev_warn(enic->netdev, + "Failed to request admin MSI-X irq: %d\n", err); + napi_disable(&enic->admin_napi); + netif_napi_del(&enic->admin_napi); + vnic_intr_free(&enic->admin_intr); + return err; + } + + enic->msix[intr_index].requested =3D 1; + + netdev_dbg(enic->netdev, + "admin channel using MSI-X interrupt (index %u)\n", + intr_index); + + return 0; +} + +static void enic_admin_teardown_intr(struct enic *enic) +{ + unsigned int intr_index =3D enic->admin_intr_index; + + napi_disable(&enic->admin_napi); + netif_napi_del(&enic->admin_napi); + + free_irq(enic->msix_entry[intr_index].vector, + enic->msix[intr_index].devid); + enic->msix[intr_index].requested =3D 0; +} + static int enic_admin_qp_type_set(struct enic *enic, u32 enable) { u64 a0 =3D QP_TYPE_ADMIN, a1 =3D enable; @@ -173,6 +417,7 @@ static int enic_admin_alloc_resources(struct enic *enic) =20 static void enic_admin_free_resources(struct enic *enic) { + vnic_intr_free(&enic->admin_intr); vnic_cq_free(&enic->admin_cq[1]); vnic_cq_free(&enic->admin_cq[0]); vnic_rq_free(&enic->admin_rq); @@ -181,6 +426,8 @@ static void enic_admin_free_resources(struct enic *enic) =20 static void enic_admin_init_resources(struct enic *enic) { + unsigned int intr_offset =3D enic->admin_intr_index; + vnic_wq_init(&enic->admin_wq, 0, 0, 0); /* cq_index, err_intr_enable, err_intr_offset */ vnic_rq_init(&enic->admin_rq, @@ -189,20 +436,34 @@ static void enic_admin_init_resources(struct enic *en= ic) VNIC_CQ_FC_DISABLE, VNIC_CQ_COLOR_ENABLE, 0, 0, 1, /* cq_head, cq_tail, cq_tail_color */ - VNIC_CQ_INTR_DISABLE, + VNIC_CQ_INTR_DISABLE, /* polled synchronously by mbox send */ VNIC_CQ_ENTRY_ENABLE, VNIC_CQ_MSG_DISABLE, - 0, /* interrupt_offset */ + intr_offset, 0 /* cq_message_addr */); vnic_cq_init(&enic->admin_cq[1], VNIC_CQ_FC_DISABLE, VNIC_CQ_COLOR_ENABLE, 0, 0, 1, /* cq_head, cq_tail, cq_tail_color */ - VNIC_CQ_INTR_DISABLE, + VNIC_CQ_INTR_ENABLE, VNIC_CQ_ENTRY_ENABLE, VNIC_CQ_MSG_DISABLE, - 0, /* interrupt_offset */ + intr_offset, 0 /* cq_message_addr */); + vnic_intr_init(&enic->admin_intr, + 0, 0, 1); /* coalescing_timer, coalescing_type, mask_on_assertion= */ +} + +static void enic_admin_msg_drain(struct enic *enic) +{ + struct enic_admin_msg *msg, *tmp; + + spin_lock_bh(&enic->admin_msg_lock); + list_for_each_entry_safe(msg, tmp, &enic->admin_msg_list, list) { + list_del(&msg->list); + kfree(msg); + } + spin_unlock_bh(&enic->admin_msg_lock); } =20 int enic_admin_channel_open(struct enic *enic) @@ -220,6 +481,18 @@ int enic_admin_channel_open(struct enic *enic) return err; } =20 + spin_lock_init(&enic->admin_msg_lock); + INIT_LIST_HEAD(&enic->admin_msg_list); + INIT_WORK(&enic->admin_msg_work, enic_admin_msg_work_handler); + + err =3D enic_admin_setup_intr(enic); + if (err) { + netdev_err(enic->netdev, + "Admin channel requires MSI-X, SR-IOV unavailable: %d\n", + err); + goto free_resources; + } + enic_admin_init_resources(enic); =20 vnic_wq_enable(&enic->admin_wq); @@ -239,15 +512,29 @@ int enic_admin_channel_open(struct enic *enic) goto disable_queues; } =20 + vnic_intr_unmask(&enic->admin_intr); + + netdev_dbg(enic->netdev, + "admin channel open: intr=3D%u wq_avail=3D%u rq_avail=3D%u cq0_color= =3D%u cq1_color=3D%u\n", + enic->admin_intr_index, + vnic_wq_desc_avail(&enic->admin_wq), + vnic_rq_desc_avail(&enic->admin_rq), + enic->admin_cq[0].last_color, + enic->admin_cq[1].last_color); + return 0; =20 disable_queues: + enic_admin_teardown_intr(enic); enic_admin_qp_type_set(enic, QP_DISABLE); if (vnic_wq_disable(&enic->admin_wq)) netdev_warn(enic->netdev, "Failed to disable admin WQ\n"); if (vnic_rq_disable(&enic->admin_rq)) netdev_warn(enic->netdev, "Failed to disable admin RQ\n"); + cancel_work_sync(&enic->admin_msg_work); + enic_admin_msg_drain(enic); enic_admin_rq_drain(enic); +free_resources: enic_admin_free_resources(enic); return err; } @@ -259,6 +546,13 @@ void enic_admin_channel_close(struct enic *enic) if (!enic->has_admin_channel) return; =20 + netdev_dbg(enic->netdev, "admin channel close\n"); + + vnic_intr_mask(&enic->admin_intr); + enic_admin_teardown_intr(enic); + cancel_work_sync(&enic->admin_msg_work); + enic_admin_msg_drain(enic); + enic_admin_qp_type_set(enic, QP_DISABLE); =20 err =3D vnic_wq_disable(&enic->admin_wq); @@ -274,5 +568,6 @@ void enic_admin_channel_close(struct enic *enic) enic_admin_rq_drain(enic); vnic_cq_clean(&enic->admin_cq[0]); vnic_cq_clean(&enic->admin_cq[1]); + vnic_intr_clean(&enic->admin_intr); enic_admin_free_resources(enic); } diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.h b/drivers/net/eth= ernet/cisco/enic/enic_admin.h index 569aadeb9312..0e52d6e0586e 100644 --- a/drivers/net/ethernet/cisco/enic/enic_admin.h +++ b/drivers/net/ethernet/cisco/enic/enic_admin.h @@ -9,7 +9,19 @@ =20 struct enic; =20 +/* Wrapper for received admin messages queued for deferred processing. + * NAPI enqueues these; a workqueue handler processes them in process cont= ext + * where sleeping (mutex, GFP_KERNEL) is safe. + */ +struct enic_admin_msg { + struct list_head list; + unsigned int len; + u8 data[] __aligned(8); +}; + int enic_admin_channel_open(struct enic *enic); void enic_admin_channel_close(struct enic *enic); +unsigned int enic_admin_wq_cq_service(struct enic *enic); +unsigned int enic_admin_rq_cq_service(struct enic *enic, unsigned int budg= et); =20 #endif /* _ENIC_ADMIN_H_ */ --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-8.cisco.com (alln-iport-8.cisco.com [173.37.142.95]) (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 962EC480DDF; Wed, 13 May 2026 15:16:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685373; cv=none; b=Vf0X56af7mv7crxO0t6gG7la5yS0zUmXL3x5m25+NV7efkEeMO8Bo+YuqgF7nC+D7B+aJkVPSR211QurkT6yag1zydasd0bRN85ansNDCnmF6Sz4H1ZLH7MAYgbiucuGkc8u4De/FA9yNnIGit7GcmgpJLBNZ03/4BtdJdqhI4s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685373; c=relaxed/simple; bh=DJOEZz0LgusiJsaMcuyJ/mo5kxauoqkYFLtqBtwJznQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NOjqQKh+2er0cPDdRqMpqWh+pfN8StiY2t2cFaObQ2YR00HEGqOyPhFgoOInlKAS/zFEHd6atNrtpdT0VfvsynWY5NJKZzBPWu25O90+r3lZBxN43mnSwfq0E9VF4NyML5E/Xo2BfvJgc59UpTukYZkxzf9R7ryCIKb1zTz8FQA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=i13/AHzV; arc=none smtp.client-ip=173.37.142.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="i13/AHzV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=3222; q=dns/txt; s=iport01; t=1778685371; x=1779894971; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=Ismjn8aCzPjNAuW3z5gQmVHzab5Wc6BkN3bhmJ9vQgA=; b=i13/AHzVSJJNZDCA0Orqzfv51oAeQWZkR64s5Ci18BtRTnR8yGF9dNJp MVPY2GiozGOzBGmya0/e26bWbzhUyvduXH6j+rgprVNC0sSE9oe8XxiFn X+gWb+jSbQ7O4lQS+ZS4CJifIfupB0moh4QQNuLYRhMMio3LogKlRYbia psjHo5Dl3d5BfPBo38YY64edOKVXsTtYyOcxGLxHmTNzv5/dtHF06HpEN rBKYEoMuFGNl7pd1ZrWnMvVyf1ekybHCNvGefSn71ih8cHeUukGXW4eed cgd7Q5CxT2dvu1rvWW/Fko9vaoO09lNLkZEkx98hF1BmRPyGrRxnWjBph Q==; X-CSE-ConnectionGUID: j8FGsQdSSwOFZwvzQ7rJCQ== X-CSE-MsgGUID: HPs/M03/Ti2OcjAeR5Xopg== X-IPAS-Result: =?us-ascii?q?A0BhAwCnlARq/5D/Ja1aglmEJ0NJhFePU4IhkU2MUBSBa?= =?us-ascii?q?w8BAQEPUQQBAYUGAo0yAiY0CQ4BAgQDAgMBAQEBAQEBAQEBAQsBAQUBAQECA?= =?us-ascii?q?QcFgQ4ThlyGWwIBAyNEEhAlAiYCAkYQBgESgwKCdAOzDHqBMoEBhH3ZRIFlC?= =?us-ascii?q?xQBgQouhXKCZwGBcIQGO4RAJxuBSUSBFAGDaIQFARmDf4JpBIMcFI54CT+BA?= =?us-ascii?q?hwDWSwBVRMNCgsHBWFSMwMgCgsSEhgVAhQcEw8EFjIdcAwnEiwXM1gbBwWBS?= =?us-ascii?q?4IFchQxBCGBAoRfeCMsA06BQwMLGA1IESw3Bg4bBD0BbgeKPx0PgT9xgQ58N?= =?us-ascii?q?WMal1aNXWuhDoQmgWSgDgEyl2aTBZkGIqMbQwlQhGiBaDyBWTMaCBsVgyJTG?= =?us-ascii?q?Q/aficyPQIHAgcNAwuReYFsAQE?= IronPort-Data: A9a23:usPw9qv0DZSVVDSRDHgQV2BELufnVJZfMUV32f8akzHdYApBsoF/q tZmKTyPbv3eMWLxKIwiYIy2pkkCvpLQnIJhSAJtqylgFypBgMeUXt7xwmUckM+xwmwvaGo9s q3yv/GZdJhcokf0/0nrav666yEgiclkf5KkYMbcICd9WAR4fykojBNnioYRj5Vh6TSDK1vlV eja/YuFYzdJ5xYuajhKs//a80s21BjPkGpwUmIWNKgjUGD2zxH5PLpHTYmtIn3xRJVjH+LSb 47r0LGj82rFyAwmA9Wjn6yTWhVirmn6ZFXmZtJ+AsBOszAazsAA+v9T2Mk0NS+7vw60c+VZk 72hg3AfpTABZcUgkMxFO/VR/roX0aduoNcrKlDn2SCfItGvn3bEm51T4E8K0YIw+LZZLnp3+ ccjNxcjXA+dldvp2pCQc7w57igjBJGD0II3oHpsy3TdSP0hW52GG/qM7t5D1zB2jcdLdRrcT 5NGMnw0M1KaPkAJYwtLYH49tL/Aan3XaDREqUmVpqof6GnIxws327/oWDbQUoPWHZoLwBnB+ Qoq+UzZOgpdEYTEjgaEqFWnhMbCp37LX5odQejQGvlCxQf7KnYoIBEfS1a+ifWwlEO7X9VRN woS9zZGhaU+6UmiXNThdxK/p3GAs1gXXN84O+4n4gilyafO5QudQG8eQVZpYdoqrsIpBjony lOEgfvtGDpp9raVIVqF/72ZqzKaIyUZLWYeIyQDSGMt59jlvZF2jR/VSNtnOLC6g8ezGjzqx T2O6i8kiN07i8MX26il1U7IjijqpZXTSAMxoALNUQqYAhhRfoWpYcmsrFPc9/sFdNnfRViat 39CkM+bhAwTMayweOW2aL1lNNmUCzyta1UwXXYH80EdygmQ IronPort-HdrOrdr: A9a23:rfKo/K9P+9IlI64hZTJuk+AuI+orL9Y04lQ7vn2ZhyYlFvBw8P rOoB1773HJYVkqNU3I9errBEDEewK/yXcX2+Ys1MmZPDUO0VHAROpfBMnZsl7d8kbFmtK1u5 0QFpRWOZncAUd3iMDi7BL9MdoxqeP3iZyAtKPyw2hgSAdyZ7ol1Qd2DQ6HDlZ7LTM2Y6bRbK DsgfZvln6HZWkdaNi9Cz0uWujOoMCOqbfdCCR2fyLOLGK1/EmVAHmQKWni4isj X-Talos-CUID: 9a23:01PN5mx3+l/SjSwie3L8BgUWSu4KaUTR90zPBGGKFnh7ceKPa3SprfY= X-Talos-MUID: 9a23:2H6qxwkfXtRKTXqixJpJdnpCDNwvxvz1T3wMy7INueCJD3FAPC+S2WE= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="740766717" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-8.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:04 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id E02BC1800048F; Wed, 13 May 2026 15:16:03 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:42 -0700 Subject: [PATCH net-next v7 05/10] enic: define MBOX message types and header structures 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-5-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=3237; i=satishkh@cisco.com; h=from:subject:message-id; bh=DJOEZz0LgusiJsaMcuyJ/mo5kxauoqkYFLtqBtwJznQ=; b=a0TE3OPEs8qmNoBXD/xHxziMZXYHFLNObiNaONuZaolkJAavjqI3SiKs4qCaMTwEtIXKyA2GX PDdMhMlB0g+D2vLcXXU5bXsUSRbvyZLD0xQX7VNGEcvirIPDJSK/KJ7 X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com Define the mailbox protocol structures for PF-VF communication: message header, generic reply, and per-message-type payloads for capability negotiation, VF registration/unregistration, and link state notification/acknowledgment. Include linux/types.h and linux/bits.h for __le16/__le32/__le64 and BIT() used in the header. Message types use an even=3Drequest / odd=3Dreply convention. The header carries source and destination VNIC IDs, a monotonically increasing message number, and the total message length. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic_mbox.h | 83 +++++++++++++++++++++++++= ++++ 1 file changed, 83 insertions(+) diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.h b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.h new file mode 100644 index 000000000000..a52f1d25cb21 --- /dev/null +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright 2025 Cisco Systems, Inc. All rights reserved. */ + +#ifndef _ENIC_MBOX_H_ +#define _ENIC_MBOX_H_ + +#include +#include + +/* + * Mailbox protocol for PF-VF communication over the admin channel. + * + * Even numbers are requests, odd numbers are replies/acks. + * The prefix indicates the initiator: VF_ =3D VF-initiated, PF_ =3D PF-in= itiated. + */ +enum enic_mbox_msg_type { + ENIC_MBOX_VF_CAPABILITY_REQUEST =3D 0, + ENIC_MBOX_VF_CAPABILITY_REPLY =3D 1, + ENIC_MBOX_VF_REGISTER_REQUEST =3D 2, + ENIC_MBOX_VF_REGISTER_REPLY =3D 3, + ENIC_MBOX_VF_UNREGISTER_REQUEST =3D 4, + ENIC_MBOX_VF_UNREGISTER_REPLY =3D 5, + ENIC_MBOX_PF_LINK_STATE_NOTIF =3D 6, + ENIC_MBOX_PF_LINK_STATE_ACK =3D 7, + ENIC_MBOX_MAX +}; + +struct enic_mbox_hdr { + __le16 src_vnic_id; + __le16 dst_vnic_id; + u8 msg_type; + u8 flags; + __le16 msg_len; + __le64 msg_num; +}; + +struct enic_mbox_generic_reply { + __le16 ret_major; + __le16 ret_minor; +}; + +#define ENIC_MBOX_ERR_GENERIC BIT(0) +#define ENIC_MBOX_ERR_VF_NOT_REGISTERED BIT(1) +#define ENIC_MBOX_ERR_MSG_NOT_SUPPORTED BIT(2) + +/* ENIC_MBOX_VF_CAPABILITY_REQUEST / _REPLY */ +#define ENIC_MBOX_CAP_VERSION_0 0 +#define ENIC_MBOX_CAP_VERSION_1 1 + +struct enic_mbox_vf_capability_msg { + __le32 version; + __le32 reserved[32]; +}; + +/* The embedded enic_mbox_generic_reply has 2-byte alignment, but the + * __le32 members give this struct 4-byte natural alignment. Receive + * buffers come from kmalloc (>=3D 8-byte aligned), so there is no + * misaligned access risk when casting from the receive buffer. + */ +struct enic_mbox_vf_capability_reply_msg { + struct enic_mbox_generic_reply reply; + __le32 version; + __le32 reserved[32]; +}; + +/* ENIC_MBOX_VF_REGISTER / _UNREGISTER */ +struct enic_mbox_vf_register_reply_msg { + struct enic_mbox_generic_reply reply; +}; + +/* ENIC_MBOX_PF_LINK_STATE_NOTIF / _ACK */ +#define ENIC_MBOX_LINK_STATE_DISABLE 0 +#define ENIC_MBOX_LINK_STATE_ENABLE 1 + +struct enic_mbox_pf_link_state_notif_msg { + __le32 link_state; +}; + +struct enic_mbox_pf_link_state_ack_msg { + struct enic_mbox_generic_reply ack; +}; + +#endif /* _ENIC_MBOX_H_ */ --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-2.cisco.com (alln-iport-2.cisco.com [173.37.142.89]) (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 05EF043CEEF; Wed, 13 May 2026 15:17:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.89 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685433; cv=none; b=OvwG9XehAT5ENzq2znypSb6RV2NIm86ZSVs8uEmz8tDyZuURXJF1V9hgUblzyyZF76F2jF+mf42gnoxFO33SJoI2f2mZSKu8zV2qRRKoDQQDBi6zkFwwceifHBS7tRe6vyEDAJp6Aeb+NboWGfSztE0+okUuom/AW0ZoIH4bMJA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685433; c=relaxed/simple; bh=nYTcXWewahIDpJ8YwPoiJgM/XQUDfXR0kD/xtzdtPGE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pTsvA+uxWpGcfalo4x6+XU6rv0lZMICN5fdnPNutshAFe8x4qKq3mcsoERnNP2GTpsfoYAU2YQU56e0nJ04M0x6KmEe1UJOn/yMUjeQccOCpVZ8g1TCDnQtv2adtaSiwZdflFVOpk1wsRENx8Xg4aolwCN3usqIMURBeYWBKjlg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=DbS/g5TE; arc=none smtp.client-ip=173.37.142.89 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="DbS/g5TE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=9317; q=dns/txt; s=iport01; t=1778685432; x=1779895032; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=yx9Ygin80aPtcXHyvhsbFph/Au5mPp3+vQdY1fqjwic=; b=DbS/g5TEMfhcVayccrgyijQSpgIKKvL1SccMCm55rqHOpGs+GlzFdVkZ NkbG6tpUDVN0YKbWIIq8GLDC+uEtvkNCaoKhWjRGB11xVQGwiBT7yeFSi zOZms4QITlUHKzlt3/jx0IL/08Y83vEFqNEznE6Agdnwvb6e/IAeFojqO Vrf8+mu7zTg1Kvl8Hl9Vy8dWSBgHvN5LvZTB2F6SIiG4XWxCmDveiHj7w dMDl8jNIR6JlKIMymef2tbXYuBzP9pwA1Sm2Vt/0TW57MEmx0BavaJU4O GotLWDW0ocatFTc3zlT55pvXVNgJLaWuHv4c3oc/AKSHQeUiPhD4vBJdp Q==; X-CSE-ConnectionGUID: 3OdfHV5DTBmfsmB/Wlr7cQ== X-CSE-MsgGUID: 5Wrgj9cGSWqANuy36j2P1A== X-IPAS-Result: =?us-ascii?q?A0BGAgCnlARq/5D/Ja1QCoJZgleBUENJhFePU4Ihnh0Ug?= =?us-ascii?q?WsPAQEBD1EEAQGFBgKNMgImNAkOAQIEAwIDAQEBAQEBAQEBAQELAQEFAQEBA?= =?us-ascii?q?gEHBYEOE4ZchlsCAQMjBFIQJQImAgJFARAGARKDAoJ0A7MMen8zgQGEfdlEg?= =?us-ascii?q?WQBCxQBgQouhXKCZwGBcIQGO4RAJxuBSUSBFAGDaIQFARAJg3+CaQSDHBSBW?= =?us-ascii?q?yCCKIpVCT+BAhwDWSwBVRMNCgsHBWFSMwMgCgsSEhgVAhQcEw8EFjIdcAwnE?= =?us-ascii?q?iwXM1gbBwWBS4IFchQxBCGBAoRfeCMsA06BQwMLGA1IESw3Bg4bBD0BbgeKP?= =?us-ascii?q?x0PgT9qBwGBDQETgSlXMRkslnqNXWuhDoQmgWSMWpM0ATKXZpMFmQYio0luh?= =?us-ascii?q?GiBaDyBWTMaCBsVgyJTGQ+OLRYczB8nMj0BAQcCBw0DC4FokAIPFweBTgEB?= IronPort-Data: A9a23:csn5JqJTh+gGsbbVFE+REZQlxSXFcZb7ZxGr2PjKsXjdYENSgWAOx mBKWW+CM/vbMDP3etkkPNu1/BhVv8OBx9JrQAYd+CA2RRqmiyZq6fd1j6vUF3nPRiEWZBs/t 63yUvGZcoZsCCSa/kvxWlTYhSEU/bmSQbbhA/LzNCl0RAt1IA8skhsLd9QR2uaEuvDnRVnW0 T/Oi5eHYgH9hmcvajt8B5+r8XuDgtyj4Fv0gXRmDRx7lAe2v2UYCpsZOZawIxPQKqFIHvS3T vr017qw+GXU5X8FUrtJRZ6iLyXm6paLVeS/oiI+t5qK23CulQRuukoPD8fwXG8M49m/c3+d/ /0W3XC4YV9B0qQhA43xWTEAe811FfUuFLMqvRFTvOTLp3AqfUcAzN01K004HbNF1tpdBG9V8 NZfFzQXMRu60rfeLLKTEoGAh+w5J8XteYdasXZ6wHSBUrAtQIvIROPB4towMDUY358VW62BI ZBENHw2MEiojx5nYj/7DLollfupnXn8cxVTqUmeouw85G27IAlZj+OyaYSLIIzVLSlTthunv G3Erm/WOS4DHfqC2GHb8CiU38aayEsXX6pXTtVU7MVCjFSNy2k7BBQIWF6/pvelzEizR7p3J kAJ/yM8oLQa+0usQd3wGRa/pRasvQMWUvJTHvc85QXLzbDbiy6QAGQeQyECbtE6uMIobTg30 FnPlNOBLSRmurCTSFqH+7uUpC/0Mi8QRUcGZCkZXU4G7sPlrYUbkB3CVJBgHbSzg9mzHiv/q xiMoTQyiqs7k8EGzeO48ErBjjbqoYLGJjPZ/S3NVW6jqwc8b4m/asnwth7Q7O1LK8CSSVzpU GU4pvVyJdsmVfml/BFhis1XdF11z55p6AHhvGM= IronPort-HdrOrdr: A9a23:kC6KpKkOPBr5dI187gXNIx9n+L3pDfLa3DAbv31ZSRFFG/FwWf re+MjzsiWUtN9xYh8dcL+7VZVoLUm3yXcx2/hyAV7AZmbbURWTTL2KhLGKq1bd8m/Fh41gPM xbH5SWZueAaGRSvILW7Ba1FtA4zMLC0qy57N2utktFfEVGZ75t6gFhBh3eKE15QwFaGYE0fa DsgPav3wDQHkg/X4CcGmQPWfTFqpngkZLrZgNDOjscgTP+9Q9BLNXBYmKlNtB0aUI1/Ysf X-Talos-CUID: 9a23:QIkuT2wKI95bGHpyzZOTBgVPPcwrUkOA4Ev6JkGjDEwud7mPFlSprfY= X-Talos-MUID: 9a23:8OnYuQoQtNHq5KoXOa4ez2xdLshqsq+BM38UuLMbqpLaN3ZIYh7I2Q== X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="737166287" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-2.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:05 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id A061218000488; Wed, 13 May 2026 15:16:04 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:43 -0700 Subject: [PATCH net-next v7 06/10] enic: add MBOX core send and receive for admin channel 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-6-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=9683; i=satishkh@cisco.com; h=from:subject:message-id; bh=nYTcXWewahIDpJ8YwPoiJgM/XQUDfXR0kD/xtzdtPGE=; b=2GYF32luHVMYZ9nVflL1FsNaYv3K7dr9cpesAuuWI8PjIVYrlNXlAzZnwBmaHdJp3Zp7h0c3i meoJ2uxid3dCbxWlvAIY5eH65TeQC3x8QjT11QSaW8vZCI8PNObi3HS X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com Implement the mailbox protocol engine used for PF-VF communication over the admin channel. The send path (enic_mbox_send_msg) builds a message with a common header, DMA-maps it, posts a single WQ descriptor with the destination vnic ID encoded in the VLAN tag field, and polls the WQ CQ for completion. The receive path (enic_mbox_recv_handler) is installed as the admin RQ callback and validates incoming message headers. PF/VF-specific dispatch will be added in subsequent commits. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/Makefile | 2 +- drivers/net/ethernet/cisco/enic/enic.h | 6 + drivers/net/ethernet/cisco/enic/enic_admin.c | 22 +++- drivers/net/ethernet/cisco/enic/enic_mbox.c | 170 +++++++++++++++++++++++= ++++ drivers/net/ethernet/cisco/enic/enic_mbox.h | 8 ++ 5 files changed, 206 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/Makefile b/drivers/net/etherne= t/cisco/enic/Makefile index 7ae72fefc99a..e38aaf34c148 100644 --- a/drivers/net/ethernet/cisco/enic/Makefile +++ b/drivers/net/ethernet/cisco/enic/Makefile @@ -4,5 +4,5 @@ obj-$(CONFIG_ENIC) :=3D enic.o enic-y :=3D enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \ enic_res.o enic_dev.o enic_pp.o vnic_dev.o vnic_rq.o vnic_vic.o \ enic_ethtool.o enic_api.o enic_clsf.o enic_rq.o enic_wq.o \ - enic_admin.o + enic_admin.o enic_mbox.o =20 diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/= cisco/enic/enic.h index 1c09da3c0b1a..42f345aceced 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -292,6 +292,8 @@ struct enic { =20 /* Admin channel resources for SR-IOV MBOX */ bool has_admin_channel; + /* set on send timeout; cleared on channel re-open */ + bool mbox_send_disabled; struct vnic_wq admin_wq; struct vnic_rq admin_rq; struct vnic_cq admin_cq[2]; @@ -304,6 +306,10 @@ struct enic { u64 admin_msg_drop_cnt; void (*admin_rq_handler)(struct enic *enic, void *buf, unsigned int len); + + /* MBOX protocol state */ + struct mutex mbox_lock; + u64 mbox_msg_num; }; =20 static inline struct net_device *vnic_get_netdev(struct vnic_dev *vdev) diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.c b/drivers/net/eth= ernet/cisco/enic/enic_admin.c index 9ebc69c7dda6..83d43e6e4d17 100644 --- a/drivers/net/ethernet/cisco/enic/enic_admin.c +++ b/drivers/net/ethernet/cisco/enic/enic_admin.c @@ -19,6 +19,7 @@ #include "cq_enet_desc.h" #include "wq_enet_desc.h" #include "rq_enet_desc.h" +#include "enic_mbox.h" =20 /* Clean up any admin WQ buffers still held by hardware at close time. * Normally buffers are freed inline after send completion, but a timed-out @@ -195,7 +196,25 @@ unsigned int enic_admin_rq_cq_service(struct enic *eni= c, unsigned int budget) goto next_desc; } =20 - enic_admin_msg_enqueue(enic, buf->os_buf, bytes_written); + if (READ_ONCE(enic->admin_rq_handler)) { + u16 sender_vlan; + + /* Firmware sets the CQ VLAN field to identify the + * sender: 0 =3D PF, 1-based =3D VF index. Overwrite + * the untrusted src_vnic_id in the MBOX header with + * the hardware-verified value. + */ + sender_vlan =3D le16_to_cpu(rq_desc->vlan); + if (bytes_written >=3D sizeof(struct enic_mbox_hdr)) { + struct enic_mbox_hdr *hdr =3D buf->os_buf; + + hdr->src_vnic_id =3D (sender_vlan =3D=3D 0) ? + cpu_to_le16(ENIC_MBOX_DST_PF) : + cpu_to_le16(sender_vlan - 1); + } + + enic_admin_msg_enqueue(enic, buf->os_buf, bytes_written); + } =20 next_desc: enic_admin_rq_buf_clean(rq, rq->to_clean); @@ -473,6 +492,7 @@ int enic_admin_channel_open(struct enic *enic) if (!enic->has_admin_channel) return -ENODEV; =20 + WRITE_ONCE(enic->mbox_send_disabled, false); err =3D enic_admin_alloc_resources(enic); if (err) { netdev_err(enic->netdev, diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.c b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.c new file mode 100644 index 000000000000..3f95247b8f6b --- /dev/null +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright 2025 Cisco Systems, Inc. All rights reserved. + +#include +#include +#include +#include + +#include "vnic_dev.h" +#include "vnic_wq.h" +#include "vnic_cq.h" +#include "enic.h" +#include "enic_admin.h" +#include "enic_mbox.h" +#include "wq_enet_desc.h" + +#define ENIC_MBOX_POLL_TIMEOUT_US 5000000 +#define ENIC_MBOX_POLL_INTERVAL_US 100 + +static void enic_mbox_fill_hdr(struct enic *enic, struct enic_mbox_hdr *hd= r, + u8 msg_type, u16 dst_vnic_id, u16 msg_len) +{ + memset(hdr, 0, sizeof(*hdr)); + hdr->dst_vnic_id =3D cpu_to_le16(dst_vnic_id); + hdr->msg_type =3D msg_type; + hdr->msg_len =3D cpu_to_le16(msg_len); + hdr->msg_num =3D cpu_to_le64(++enic->mbox_msg_num); +} + +int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id, + void *payload, u16 payload_len) +{ + u16 total_len =3D sizeof(struct enic_mbox_hdr) + payload_len; + struct vnic_wq *wq =3D &enic->admin_wq; + struct wq_enet_desc *desc; + unsigned long timeout; + dma_addr_t dma_addr; + u16 vlan_tag; + void *buf; + int err; + + /* Serialize MBOX sends. The admin channel is a low-frequency + * control path; holding the mutex across the poll is acceptable. + */ + mutex_lock(&enic->mbox_lock); + + if (!enic->has_admin_channel || READ_ONCE(enic->mbox_send_disabled)) { + err =3D -ENODEV; + goto unlock; + } + + if (vnic_wq_desc_avail(wq) =3D=3D 0) { + err =3D -ENOSPC; + goto unlock; + } + + buf =3D kmalloc(total_len, GFP_KERNEL); + if (!buf) { + err =3D -ENOMEM; + goto unlock; + } + + enic_mbox_fill_hdr(enic, buf, msg_type, dst_vnic_id, total_len); + if (payload_len) { + void *dst =3D buf + sizeof(struct enic_mbox_hdr); + + memcpy(dst, payload, payload_len); + } + + dma_addr =3D dma_map_single(&enic->pdev->dev, buf, total_len, + DMA_TO_DEVICE); + if (dma_mapping_error(&enic->pdev->dev, dma_addr)) { + kfree(buf); + err =3D -ENOMEM; + goto unlock; + } + + /* Firmware uses vlan field for routing: 0 =3D PF, 1-based =3D VF index */ + if (dst_vnic_id =3D=3D ENIC_MBOX_DST_PF) + vlan_tag =3D 0; + else + vlan_tag =3D dst_vnic_id + 1; + + desc =3D vnic_wq_next_desc(wq); + wq_enet_desc_enc(desc, (u64)dma_addr | VNIC_PADDR_TARGET, + total_len, + 0, 0, 0, /* mss, hdr_len, offload_mode */ + 1, 1, /* eop, cq_entry */ + 0, /* fcoe_encap */ + 1, vlan_tag, /* vlan_tag_insert, vlan_tag */ + 0); /* loopback */ + vnic_wq_post(wq, buf, dma_addr, total_len, + 1, 1, /* sop, eop */ + 1, 1, /* desc_skip_cnt, cq_entry */ + 0, 0); /* compressed_send, wrid */ + vnic_wq_doorbell(wq); + + timeout =3D jiffies + usecs_to_jiffies(ENIC_MBOX_POLL_TIMEOUT_US); + err =3D -ETIMEDOUT; + while (time_before(jiffies, timeout)) { + if (enic_admin_wq_cq_service(enic)) { + err =3D 0; + break; + } + usleep_range(ENIC_MBOX_POLL_INTERVAL_US, + ENIC_MBOX_POLL_INTERVAL_US + 50); + } + /* Final check in case completion arrived during the last sleep */ + if (err && enic_admin_wq_cq_service(enic)) + err =3D 0; + + if (!err) { + wq->to_clean =3D wq->to_clean->next; + wq->ring.desc_avail++; + dma_unmap_single(&enic->pdev->dev, dma_addr, total_len, + DMA_TO_DEVICE); + kfree(buf); + } else { + netdev_err(enic->netdev, + "MBOX send timed out (type %u dst %u), disabling channel\n", + msg_type, dst_vnic_id); + /* + * The WQ descriptor is still live in hardware. Do not unmap + * or free the buffer: the device may still DMA from dma_addr. + * Mark the channel unusable so no further sends are attempted. + */ + WRITE_ONCE(enic->mbox_send_disabled, true); + } + + netdev_dbg(enic->netdev, + "MBOX send msg_type %u dst %u vlan %u err %d\n", + msg_type, dst_vnic_id, vlan_tag, err); +unlock: + mutex_unlock(&enic->mbox_lock); + return err; +} + +static void enic_mbox_recv_handler(struct enic *enic, void *buf, + unsigned int len) +{ + struct enic_mbox_hdr *hdr =3D buf; + + if (len < sizeof(*hdr)) { + if (net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: truncated message (len %u < %zu)\n", + len, sizeof(*hdr)); + return; + } + + if (hdr->msg_type >=3D ENIC_MBOX_MAX) { + if (net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: unknown msg type %u\n", + hdr->msg_type); + return; + } + + netdev_dbg(enic->netdev, + "MBOX recv: type %u from vnic %u len %u\n", + hdr->msg_type, le16_to_cpu(hdr->src_vnic_id), + le16_to_cpu(hdr->msg_len)); +} + +void enic_mbox_init(struct enic *enic) +{ + enic->mbox_msg_num =3D 0; + mutex_init(&enic->mbox_lock); + WRITE_ONCE(enic->admin_rq_handler, enic_mbox_recv_handler); +} diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.h b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.h index a52f1d25cb21..73fd7f783ee2 100644 --- a/drivers/net/ethernet/cisco/enic/enic_mbox.h +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.h @@ -80,4 +80,12 @@ struct enic_mbox_pf_link_state_ack_msg { struct enic_mbox_generic_reply ack; }; =20 +#define ENIC_MBOX_DST_PF 0xFFFF + +struct enic; + +void enic_mbox_init(struct enic *enic); +int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id, + void *payload, u16 payload_len); + #endif /* _ENIC_MBOX_H_ */ --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-4.cisco.com (alln-iport-4.cisco.com [173.37.142.91]) (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 2AE8248BD3D; Wed, 13 May 2026 15:17:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.91 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685456; cv=none; b=A+uJAsljtJNJohIUKCyFbxzCJ7fN36G+vr7LFwYLkWUiS9TK9rPi3Dm9Q7V2Ue1V3BGg0VojVF8ob+4JQQ9sVXmqWVk+xVSYIbzMXMyR/yrh/CnTwsIYcBMEqQ67aG11eJMqGv70c6CdbphFtvvMPD1oh0DeHdK5aSlqsdTN9X0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685456; c=relaxed/simple; bh=AZ5PLVgR9SM+hDj0pC3rqRP3gdUywtSJM5oByfueS84=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tVF1fNjugh9KYLe5LMwjH1CeN920pgZ8uX53CW9VZqzSWSuEBzWWCP3zxHfqimawWKAEEj9BiOr8m6SAQgfouIT94wT38QzNIztcRUKxYoll51iipt/bqHkZi4hWNGCzG835YREXiuqxhj6WDN3OBeUxcz0E/XEekToIqCMNYVk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=dgIzZvle; arc=none smtp.client-ip=173.37.142.91 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="dgIzZvle" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=8596; q=dns/txt; s=iport01; t=1778685455; x=1779895055; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=2/NcobUlyGgrCLakC44OQHqYS7iM+bDK2LrV5Q4q8sA=; b=dgIzZvleY6xtR8rWU/iWxJ6S9xDeA+I1bz3oMCA92bkZu3bGxErBQHpm c8k+Bkn5X3LKbK/QBHKJMpfQsHnhlEDdvpOKjAtjTM2GX3RtyfJVNVGWx aqr9Fl9YiAmHJRcLLtpVWQZ0bckge5hD3bLYQll+XnA3Phx8TLLH1aKCc PorvRV0yG6DEo7Id0dxywQuIl0Gik0Hoct0tj2AfchzzPSolyjck94qdL TkofK8CAwQXdCs5TvV5couef21pvNKl+kzJZGadz2STQ/SZ8FaSJ7iJ/9 9u4ORH3F7KoKkqwPpyQ5moPGj/hHaPmM9ggha9Z2AUigCarTUGEhtClVS Q==; X-CSE-ConnectionGUID: YNDV3mz4T12IwmhrivdIRw== X-CSE-MsgGUID: 28VrWugYSYK+xKysDWRBSA== X-IPAS-Result: =?us-ascii?q?A0BGAgA0lQRq/5D/Ja1aglmCGD+BUENJhFePU4IhkU2MU?= =?us-ascii?q?BSBaw8BAQEPUQQBAYUGAo0yAiY0CQ4BAgQDAgMBAQEBAQEBAQEBAQsBAQUBA?= =?us-ascii?q?QECAQcFgQ4ThlyGWwIBAyMEUhAlAiYCAkYQBgESgipYgnQDsw96fzOBAYR92?= =?us-ascii?q?USBZAELFAGBCi6FcoJnAYFwhAY7hEAnG4FJRIEVg2iEBRqDf4JpBIMcFIM4i?= =?us-ascii?q?0AJP4ECHANZLAFVEw0KCwcFYVIzAyAKCxISGBUCFBwTDwQWMh1wDBAXEiwXM?= =?us-ascii?q?1gbBwWBS4IFchQxBCGBAoRfeCMsA06BQwMLGA1IESw3Bg4bBD0BbgeKPx0Pg?= =?us-ascii?q?T9qB0swFEI5MQF7BTCTCx2Dfo1da4E1n1mEJoFkoA4BMpdmkwWZBiKjTGuEa?= =?us-ascii?q?IFoPIFZMxoIGxWDIlMZD44tFhzMIicyPQIHAgcNAwuReYFsAQE?= IronPort-Data: A9a23:gJplyKmcIp4iNL6qk/fMWnjo5gxBJ0RdPkR7XQ2eYbSJt1+Wr1Gzt xJNC2rXbvyOYzSmedp0bYjg9E8DsZfTzYNjSgBk/ywyQ1tH+JHPbTi7wugcHM8zwunrFh8PA xA2M4GYRCwMZiaC4E/raf658SUUOZigHtLUEPTDNj16WThqQSIgjQMLs+Mii+aEu/Dha++2k Y20+Za31GONgWYubDpJsvnb8XuDgdyr0N8mlg1mDRx0lAe2e0k9VPo3Oay3Jn3kdYhYdsbSb /rD1ryw4lTC9B4rDN6/+p6jGqHdauePVeQmoiM+t5mK2nCulARrukoIHKZ0hXNsttm8t4sZJ OOhGnCHYVxB0qXkwIzxWvTDes10FfUuFLTveRBTvSEPpqHLWyOE/hlgMK05Fbw+1tgsBHMSy aVCCS8IbgqCme6X+q3uH4GAhux7RCXqFJkUtnclyXTSCuwrBMicBa7L/tRfmjw3g6iiH96HO JFfMmUpNkmdJUQTZj/7C7pm9AusrmL2bzxDqFGVjaE2+GPUigd21dABNfKKIY3VGp0Jxh/wS mTupTTHGC4HO+2k+BnG4lG9ncPwpwnAcddHfFG/3rsw6LGJ/UQfAQMbUHO3qOe0j0q5Vc4ZL UEIkgIjobU3/V6mUvHyWBq3pHPCtRkZM/JTDuczwAKA0KzZ50CeHGdsZjdHZMYrq4wwSCAm2 0Ghm87vA3pksNW9UXuX+7GVhSm/NSgcMSkJYipsZQ8E5cTz5YI+lBTCSv59H6OvyN74Azf9x 3aNtidWr7MekcIGyY2l8l3dxTGhvJ7ESkgy/Aq/Y46+xhlyaIjgY8mj7kLWqK4fao2YVVKG+ nMDnqBy8dwzMH1ErwTVKM1lIV1jz6nt3OH06bK3I6Qcyg== IronPort-HdrOrdr: A9a23:4NztOanKes8EXZRzaU2Ezra43FvpDfLa3DAbv31ZSRFFG/FwWf re+MjzsiWUtN9xYh8dcL+7VZVoLUm3yXcx2/hyAV7AZmbbURWTTL2KhLGKq1bd8m/Fh41gPM xbH5SWZueAaGRSvILW7Ba1FtA4zMLC0qy57N2utktFfEVGZ75t6gFhBh3eKE15QwFaGYE0fa DsgPav3wDQHkg/X4CcGmQPWfTFqpngkZLrZgNDOjscgTP+9Q9BLNXBYmKlNtB0aUI1/Ysf X-Talos-CUID: =?us-ascii?q?9a23=3ADO8sa2qzxWaauLHPpP0Y7oDmUfEDXkOGyWWMHxb?= =?us-ascii?q?iKHlsSKeUV1Oxwrwxxg=3D=3D?= X-Talos-MUID: 9a23:te+NwgvabpUV9/rros2n3mFcLvh17JWVOWNOgbYXoOW7DwZLEmLI X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="739770401" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-4.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:06 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id 5E79B1800020F; Wed, 13 May 2026 15:16:05 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:44 -0700 Subject: [PATCH net-next v7 07/10] enic: add MBOX PF handlers for VF register and capability 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-7-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=8938; i=satishkh@cisco.com; h=from:subject:message-id; bh=AZ5PLVgR9SM+hDj0pC3rqRP3gdUywtSJM5oByfueS84=; b=y2TCL8QXj4hOZCUzIH8HTUXdKshMt6Rp4yMEK5lIK4pmFTuhVT9J6evge8GYmWEU//aRZKjl7 PGy2C43kXCRDQgnBLIDjcqdqXGg4tg3ZGRiQDf/5sGJy2xHTRktLJdj X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com Implement PF-side mailbox message processing for SR-IOV V2 admin channel communication. When the PF receives messages from VFs, the dispatch routes them to type-specific handlers: - VF_CAPABILITY_REQUEST: reply with protocol version 1 - VF_REGISTER_REQUEST: mark VF registered, reply, then send PF_LINK_STATE_NOTIF with link enabled - VF_UNREGISTER_REQUEST: mark VF unregistered, send reply - PF_LINK_STATE_ACK: log errors from VF acknowledgment Per-VF state (struct enic_vf_state) is tracked via enic->vf_state which will be allocated when SRIOV V2 is enabled. Remove the CONFIG_PCI_IOV guard from num_vfs in struct enic. The PF handlers reference enic->num_vfs for VF ID bounds checking in enic_mbox.c, which is compiled unconditionally. The field must be visible regardless of CONFIG_PCI_IOV to avoid build failures. Add enic_mbox_send_link_state() helper for PF-initiated link state notifications, also used later by ndo_set_vf_link_state. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic.h | 7 +- drivers/net/ethernet/cisco/enic/enic_mbox.c | 184 ++++++++++++++++++++++++= +++- drivers/net/ethernet/cisco/enic/enic_mbox.h | 1 + 3 files changed, 188 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/= cisco/enic/enic.h index 42f345aceced..9b1fa3857df5 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -256,9 +256,7 @@ struct enic { struct enic_rx_coal rx_coalesce_setting; u32 rx_coalesce_usecs; u32 tx_coalesce_usecs; -#ifdef CONFIG_PCI_IOV u16 num_vfs; -#endif enum enic_vf_type vf_type; unsigned int enable_count; spinlock_t enic_api_lock; @@ -310,6 +308,11 @@ struct enic { /* MBOX protocol state */ struct mutex mbox_lock; u64 mbox_msg_num; + + /* PF: per-VF MBOX state, allocated when SRIOV V2 is enabled */ + struct enic_vf_state { + bool registered; + } *vf_state; }; =20 static inline struct net_device *vnic_get_netdev(struct vnic_dev *vdev) diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.c b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.c index 3f95247b8f6b..0f7f9d2d091f 100644 --- a/drivers/net/ethernet/cisco/enic/enic_mbox.c +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.c @@ -135,10 +135,177 @@ int enic_mbox_send_msg(struct enic *enic, u8 msg_typ= e, u16 dst_vnic_id, return err; } =20 +int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state) +{ + struct enic_mbox_pf_link_state_notif_msg notif =3D {}; + + if (!enic->vf_state || vf_id >=3D enic->num_vfs || + !enic->vf_state[vf_id].registered) { + netdev_dbg(enic->netdev, + "MBOX: skip link state to unregistered VF %u\n", + vf_id); + return 0; + } + + notif.link_state =3D cpu_to_le32(link_state); + return enic_mbox_send_msg(enic, ENIC_MBOX_PF_LINK_STATE_NOTIF, vf_id, + ¬if, sizeof(notif)); +} + +static int enic_mbox_pf_handle_capability(struct enic *enic, void *msg, + u16 vf_id, u64 msg_num) +{ + struct enic_mbox_vf_capability_reply_msg reply =3D {}; + + reply.reply.ret_major =3D cpu_to_le16(0); + reply.version =3D cpu_to_le32(ENIC_MBOX_CAP_VERSION_1); + + return enic_mbox_send_msg(enic, ENIC_MBOX_VF_CAPABILITY_REPLY, vf_id, + &reply, sizeof(reply)); +} + +static int enic_mbox_pf_handle_register(struct enic *enic, void *msg, + u16 vf_id, u64 msg_num) +{ + struct enic_mbox_vf_register_reply_msg reply =3D {}; + int err; + + if (!enic->vf_state || vf_id >=3D enic->num_vfs) { + if (net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: register from invalid VF %u\n", + vf_id); + return -EINVAL; + } + + /* VF re-registering (e.g. guest reboot without clean unregister): + * mark the previous registration inactive before accepting the new one. + */ + if (enic->vf_state[vf_id].registered) { + netdev_dbg(enic->netdev, + "MBOX: VF %u re-register, cleaning previous state\n", + vf_id); + enic->vf_state[vf_id].registered =3D false; + } + + reply.reply.ret_major =3D cpu_to_le16(0); + err =3D enic_mbox_send_msg(enic, ENIC_MBOX_VF_REGISTER_REPLY, vf_id, + &reply, sizeof(reply)); + if (err) + return err; + + enic->vf_state[vf_id].registered =3D true; + if (net_ratelimit()) + netdev_info(enic->netdev, "VF %u registered via MBOX\n", vf_id); + + err =3D enic_mbox_send_link_state(enic, vf_id, + ENIC_MBOX_LINK_STATE_ENABLE); + if (err) + netdev_warn(enic->netdev, + "VF %u: failed to send initial link state: %d\n", + vf_id, err); + /* Registration succeeded; link state will be (re-)sent on next + * enic_link_check() event. + */ + return 0; +} + +static int enic_mbox_pf_handle_unregister(struct enic *enic, void *msg, + u16 vf_id, u64 msg_num) +{ + struct enic_mbox_vf_register_reply_msg reply =3D {}; + int err; + + if (!enic->vf_state || vf_id >=3D enic->num_vfs) { + if (net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: unregister from invalid VF %u\n", + vf_id); + return -EINVAL; + } + + /* VF is unloading; clear local state regardless of whether + * the reply is successfully delivered to avoid the PF treating + * a dead VF as still registered. + */ + enic->vf_state[vf_id].registered =3D false; + + reply.reply.ret_major =3D cpu_to_le16(0); + err =3D enic_mbox_send_msg(enic, ENIC_MBOX_VF_UNREGISTER_REPLY, vf_id, + &reply, sizeof(reply)); + + if (net_ratelimit()) + netdev_info(enic->netdev, "VF %u unregistered via MBOX\n", vf_id); + + return err; +} + +static void enic_mbox_pf_process_msg(struct enic *enic, + struct enic_mbox_hdr *hdr, void *payload) +{ + u16 vf_id =3D le16_to_cpu(hdr->src_vnic_id); + u16 msg_len =3D le16_to_cpu(hdr->msg_len); + int err =3D 0; + + if (!enic->vf_state) { + netdev_dbg(enic->netdev, + "MBOX: PF received msg but SRIOV not active\n"); + return; + } + + if (vf_id >=3D enic->num_vfs) { + if (net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: PF received msg from invalid VF %u\n", + vf_id); + return; + } + + switch (hdr->msg_type) { + case ENIC_MBOX_VF_CAPABILITY_REQUEST: + err =3D enic_mbox_pf_handle_capability(enic, payload, vf_id, + le64_to_cpu(hdr->msg_num)); + break; + case ENIC_MBOX_VF_REGISTER_REQUEST: + err =3D enic_mbox_pf_handle_register(enic, payload, vf_id, + le64_to_cpu(hdr->msg_num)); + break; + case ENIC_MBOX_VF_UNREGISTER_REQUEST: + err =3D enic_mbox_pf_handle_unregister(enic, payload, vf_id, + le64_to_cpu(hdr->msg_num)); + break; + case ENIC_MBOX_PF_LINK_STATE_ACK: { + struct enic_mbox_pf_link_state_ack_msg *ack =3D payload; + + if (msg_len < sizeof(*hdr) + sizeof(*ack)) + break; + if (le16_to_cpu(ack->ack.ret_major)) + netdev_warn(enic->netdev, + "MBOX: VF %u link state ACK error %u/%u\n", + vf_id, le16_to_cpu(ack->ack.ret_major), + le16_to_cpu(ack->ack.ret_minor)); + break; + } + default: + netdev_dbg(enic->netdev, + "MBOX: PF unhandled msg type %u from VF %u\n", + hdr->msg_type, vf_id); + err =3D -EOPNOTSUPP; + break; + } + + if (err && net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: PF handler for msg type %u from VF %u failed: %d\n", + hdr->msg_type, vf_id, err); +} + static void enic_mbox_recv_handler(struct enic *enic, void *buf, unsigned int len) { struct enic_mbox_hdr *hdr =3D buf; + void *payload; + u16 msg_len; =20 if (len < sizeof(*hdr)) { if (net_ratelimit()) @@ -156,10 +323,23 @@ static void enic_mbox_recv_handler(struct enic *enic,= void *buf, return; } =20 + msg_len =3D le16_to_cpu(hdr->msg_len); + if (msg_len < sizeof(*hdr) || msg_len > len) { + if (net_ratelimit()) + netdev_warn(enic->netdev, + "MBOX: invalid msg_len %u (buf len %u)\n", + msg_len, len); + return; + } + netdev_dbg(enic->netdev, "MBOX recv: type %u from vnic %u len %u\n", - hdr->msg_type, le16_to_cpu(hdr->src_vnic_id), - le16_to_cpu(hdr->msg_len)); + hdr->msg_type, le16_to_cpu(hdr->src_vnic_id), msg_len); + + payload =3D buf + sizeof(*hdr); + + if (enic->vf_state) + enic_mbox_pf_process_msg(enic, hdr, payload); } =20 void enic_mbox_init(struct enic *enic) diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.h b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.h index 73fd7f783ee2..f1de67db1273 100644 --- a/drivers/net/ethernet/cisco/enic/enic_mbox.h +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.h @@ -87,5 +87,6 @@ struct enic; void enic_mbox_init(struct enic *enic); int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id, void *payload, u16 payload_len); +int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state= ); =20 #endif /* _ENIC_MBOX_H_ */ --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-4.cisco.com (alln-iport-4.cisco.com [173.37.142.91]) (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 2D09B48AE29; Wed, 13 May 2026 15:17:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.91 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685455; cv=none; b=mIFAnDRr78enGk6cub+iDpp06+1lCDECybURdlcwtGOx21AVp9VnkFGht3H1uCk+EMeeNTafGiq8fdRnU8IIziSH/BOi4c4UQJTASw7myCv9/KwK/sCHLfQzPk/MqjPaxjhSa8kOp4TO7z0oUsE/xQRWMiTNBtXN/3+trdANGzk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685455; c=relaxed/simple; bh=GALO7ss/CgXpxjOeb6TDPZCTq+4qPsroBx0VC58dydE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AmQgsZNq+flHJha0muHZwYqSoSmaXL4qakd6N7xAg84zTew7yAxBAwQRHpR7WQQE9Hwm4s+v+kIeAaPf7R3/xB3M+2OUdYJUu6rC1KTz/FLGkS+Me2aKheFzA6Wua/8Ptbjn74PBfyGJB2qAp59bCukNa8gwvDwzAnZ6LMsIakA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=UWj6jyuz; arc=none smtp.client-ip=173.37.142.91 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="UWj6jyuz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=11275; q=dns/txt; s=iport01; t=1778685453; x=1779895053; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=rvtO22Z6OkZX2lcTtsRaaXcNd+I0AosB4BqFpvYI89E=; b=UWj6jyuz00oeop6/LoX+0CiSaV/cDOC6+3hTeZNX7h5PqbXmOaUi2r/3 bhlHevnURZJPQY6I6YoUiO1KKwIDrNziBVjdbigzsD/B8GeklEGgCiLlK p48rFowy1gytcN7yVfW9YF+D8bavxJPmbHNaVgr/aZnUcvZkjUDj6ISXl xrd71ivsGIz8w+CRoG0Kxlk72J7Go2lROviqBtf+wpksypZ8EJkNaGrx+ SOPXes+dFbG98OaZEbNxG3wfjdyRDdFwoqM467AIILDkmgjG8pfU8BfTV KTkPm+blvOyumDNvfFo+dUl1PVj6ddFNbomzqrs0nprkVjMY9ySu0l/O4 A==; X-CSE-ConnectionGUID: poGM18+CTRmTgQpmUSLndQ== X-CSE-MsgGUID: VRBv2Ny6TUqCpHdQYV0w0Q== X-IPAS-Result: =?us-ascii?q?A0BGAgA0lQRq/5D/Ja1aHgEBCxIMggULgleBUENJhFePU?= =?us-ascii?q?4IhgRadBxSBaw8BAQEPUQQBAYUGAo0yAiY0CQ4BAgQDAgMBAQEBAQEBAQEBA?= =?us-ascii?q?QsBAQUBAQECAQcFgQ4ThlyGWwIBAyMEQBIQJQImAgJGEAYBEoMCgnQDsw96f?= =?us-ascii?q?zOBAd5BgWQBCxQBgQouhXKCZwGBcIQGO4RAJxuBSUSBFYJydoQFBRWDf4JpB?= =?us-ascii?q?IINgQ8UjngJP4ECHANZLAFVEw0KCwcFYVIzAyAKCxISGBUCFC8PBBYyHXAME?= =?us-ascii?q?BcSLBczWBsHBYFLggVyFDEEIYEChF94IywDToFDAwsYDUgRLDcGDhsEPQFuB?= =?us-ascii?q?4o/HQ+BP2oHFidSezFnFQUwCZNhgzyNXWuBNZ9ZhCaBZKAOATKEBJNikwWZB?= =?us-ascii?q?iKCNqExUIRogWg8gVkzGggbFYMiUxkPji0WHMwiJzI9AgcCBw0DC5FoEReBV?= =?us-ascii?q?QEB?= IronPort-Data: A9a23:irRd6a4XJ+yszodM8CvWUgxRtPjGchMFZxGqfqrLsTDasY5as4F+v mUdD26BO/eJZjPxLd12bNni8h4D78fWm4VqSFNrqSgxZn8b8sCt6fZ1gavT04J+CuWZESqLO u1HMoGowPgcFyGa/lH2dOC98RGQ7InQLpLkEunIJyttcgFtTSYlmHpLlvUw6mJSqYDR7zil5 5Wo+KUzBHf/g2Qqaj9NsPrawP9SlK2aVA0w7wRWic9j5Dcyp1FNZLoDKKe4KWfPQ4U8NoaSW +bZwbilyXjS9hErB8nNuu6TnpoiG+O60aCm0xK6aoD66vRwjnVaPpUTaJLwXXxqZwChxLid/ jniWauYEm/FNoWU8AgUvoIx/ytWZcWq85efSZSzXFD6I0DuKxPRL/tS4E4eJYo3378nQkpyz /kkJwkVay24o+S6+efuIgVsrpxLwMjDJogTvDRkiDreF/tjGc+FSKTR7tge1zA17ixMNa+BP IxCNnw1MUmGOkETUrsUIMpWcOOAnXDjciZYq1K9rqss6G+Vxwt0uFToGIWOK4PVHZkNwC50o Er4xU7nWDcLauCi0BGd0n6Vt9GXgnvCDdd6+LqQs6QCbEeo7mAaFhATfVeyv/S8jkmwR5RZJ lB80icisK075kG3Ztb6WBK8rTiPuRt0c9lNGeQS6wyXzKfQpQGDCQAsRzhNctE598k7WTAny HeNgtXvQzdv2JWNQHiQ8La8tz6+OSEJa2QFYEcsSQoD/smmo4wpiB/LZshsHbTzjdDvHzz0h TeQo0AWgbgPgcMV/7u08EqBgD+2oJXNCAkv6W3qsnmN9Ah1YsuhIoev81WetakGJ4eCRV7Ht 38B8ySD0N0z4Vi2vHTlaI0w8HuBt55p7BW0bYZTIqQc IronPort-HdrOrdr: A9a23:SV2Tg61s/SZ0QIL2tdxL9gqjBEQkLtp133Aq2lEZdPWaSL39qy nIppUmPH7P5gr5N0tMpTntAsO9qDbnhPxICOoqUotKIjOHhILAFugLhrcKgQeQeBEWndQw6U 4PSdkaNPTASXV3ksr+5hC1CJIDzMnvytHQuc7ui1pgUg1ubbht9ENCCgidGlBrXwUuP+teKH Pl3LshmxOQPVIKc8+8Gn4JG8LHp9HNidbaRCRuPW9e1OFL5gnYkoIT1HOjr2wjbw8= X-Talos-CUID: 9a23:U4wIpmCzlx8Az3b6EzFg22tNSoMOTkfY8HjpO0qFMkJvRITAHA== X-Talos-MUID: =?us-ascii?q?9a23=3Asyc3rA2vC9eHMMAKmJuneCu6DzUj3Z6EFhorgMs?= =?us-ascii?q?6htCvLQx8Agaj1Cvve9py?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="739770406" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-4.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:06 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id 1A04B1800048F; Wed, 13 May 2026 15:16:06 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:45 -0700 Subject: [PATCH net-next v7 08/10] enic: add MBOX VF handlers for capability, register and link state 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-8-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685359; l=11680; i=satishkh@cisco.com; h=from:subject:message-id; bh=GALO7ss/CgXpxjOeb6TDPZCTq+4qPsroBx0VC58dydE=; b=qZ5frxFkLttSJI+RXMWWhTRKENIM2cJ90K36hZoof47RNrHgeE79z0o+WpsS30fpK4cnYPrJg atEJ2BkQZw+BOIkPcUxt8huosyH5ivrgpwqPubZxRmpsOBOn/BzSNnh X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com Implement VF-side mailbox message processing for SR-IOV V2 admin channel communication. VF receive handlers: - VF_CAPABILITY_REPLY: store PF protocol version, signal completion - VF_REGISTER_REPLY: mark VF as registered, signal completion - VF_UNREGISTER_REPLY: mark VF as unregistered, signal completion - PF_LINK_STATE_NOTIF: update carrier state via netif_carrier_on/off, send ACK back to PF VF initiation functions for the probe-time handshake: - enic_mbox_vf_capability_check: send capability request, wait for PF reply via completion - enic_mbox_vf_register: send register request, wait for PF confirmation via completion - enic_mbox_vf_unregister: send unregister request, wait for PF confirmation The wait helper (enic_mbox_wait_reply) uses wait_for_completion_timeout, signaled when the admin ISR/NAPI/ workqueue pipeline delivers the reply message. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic.h | 17 +- drivers/net/ethernet/cisco/enic/enic_mbox.c | 256 ++++++++++++++++++++++++= ++++ drivers/net/ethernet/cisco/enic/enic_mbox.h | 3 + 3 files changed, 275 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/= cisco/enic/enic.h index 9b1fa3857df5..483053c781df 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -258,6 +258,8 @@ struct enic { u32 tx_coalesce_usecs; u16 num_vfs; enum enic_vf_type vf_type; + bool vf_registered; + u32 pf_cap_version; unsigned int enable_count; spinlock_t enic_api_lock; bool enic_api_busy; @@ -305,9 +307,22 @@ struct enic { void (*admin_rq_handler)(struct enic *enic, void *buf, unsigned int len); =20 - /* MBOX protocol state */ + /* MBOX protocol state -- single-flight: on the VF, all callers + * that wait on mbox_comp run under RTNL or during probe/remove, + * so only one completion is outstanding at a time. mbox_lock + * protects the shared admin WQ from concurrent senders. + */ struct mutex mbox_lock; u64 mbox_msg_num; + struct completion mbox_comp; + /* Type of reply the current waiter on mbox_comp expects. Set + * under mbox_lock before reinit_completion(); cleared after + * wait_reply returns. Reply handlers compare against the + * incoming reply type and drop stale replies from previously + * timed-out requests instead of waking the unrelated current + * waiter. + */ + u8 mbox_expected_reply; =20 /* PF: per-VF MBOX state, allocated when SRIOV V2 is enabled */ struct enic_vf_state { diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.c b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.c index 0f7f9d2d091f..b555362379b3 100644 --- a/drivers/net/ethernet/cisco/enic/enic_mbox.c +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.c @@ -5,6 +5,7 @@ #include #include #include +#include =20 #include "vnic_dev.h" #include "vnic_wq.h" @@ -135,6 +136,16 @@ int enic_mbox_send_msg(struct enic *enic, u8 msg_type,= u16 dst_vnic_id, return err; } =20 +static int enic_mbox_wait_reply(struct enic *enic, unsigned long timeout_m= s) +{ + unsigned long left; + + left =3D wait_for_completion_timeout(&enic->mbox_comp, + msecs_to_jiffies(timeout_ms)); + + return left ? 0 : -ETIMEDOUT; +} + int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state) { struct enic_mbox_pf_link_state_notif_msg notif =3D {}; @@ -300,6 +311,157 @@ static void enic_mbox_pf_process_msg(struct enic *eni= c, hdr->msg_type, vf_id, err); } =20 +static void enic_mbox_vf_handle_capability_reply(struct enic *enic, + void *payload) +{ + struct enic_mbox_vf_capability_reply_msg *reply =3D payload; + + if (enic->mbox_expected_reply !=3D ENIC_MBOX_VF_CAPABILITY_REPLY) { + netdev_warn(enic->netdev, + "MBOX: stale capability reply (expected %u), drop\n", + enic->mbox_expected_reply); + return; + } + + if (le16_to_cpu(reply->reply.ret_major) =3D=3D 0) + enic->pf_cap_version =3D le32_to_cpu(reply->version); + complete(&enic->mbox_comp); +} + +static void enic_mbox_vf_handle_register_reply(struct enic *enic, + void *payload) +{ + struct enic_mbox_vf_register_reply_msg *reply =3D payload; + + if (enic->mbox_expected_reply !=3D ENIC_MBOX_VF_REGISTER_REPLY) { + netdev_warn(enic->netdev, + "MBOX: stale register reply (expected %u), drop\n", + enic->mbox_expected_reply); + return; + } + + if (le16_to_cpu(reply->reply.ret_major)) { + netdev_warn(enic->netdev, + "MBOX: VF register rejected by PF: %u/%u\n", + le16_to_cpu(reply->reply.ret_major), + le16_to_cpu(reply->reply.ret_minor)); + } else { + enic->vf_registered =3D true; + } + complete(&enic->mbox_comp); +} + +static void enic_mbox_vf_handle_unregister_reply(struct enic *enic, + void *payload) +{ + struct enic_mbox_vf_register_reply_msg *reply =3D payload; + + if (enic->mbox_expected_reply !=3D ENIC_MBOX_VF_UNREGISTER_REPLY) { + netdev_warn(enic->netdev, + "MBOX: stale unregister reply (expected %u), drop\n", + enic->mbox_expected_reply); + return; + } + + if (le16_to_cpu(reply->reply.ret_major)) { + netdev_warn(enic->netdev, + "MBOX: VF unregister rejected by PF: %u/%u\n", + le16_to_cpu(reply->reply.ret_major), + le16_to_cpu(reply->reply.ret_minor)); + } else { + enic->vf_registered =3D false; + } + complete(&enic->mbox_comp); +} + +static void enic_mbox_vf_handle_link_state(struct enic *enic, void *payloa= d) +{ + struct enic_mbox_pf_link_state_notif_msg *notif =3D payload; + struct enic_mbox_pf_link_state_ack_msg ack =3D {}; + + switch (le32_to_cpu(notif->link_state)) { + case ENIC_MBOX_LINK_STATE_ENABLE: + if (!netif_carrier_ok(enic->netdev)) + netif_carrier_on(enic->netdev); + netdev_dbg(enic->netdev, "MBOX: link state -> UP\n"); + break; + case ENIC_MBOX_LINK_STATE_DISABLE: + if (netif_carrier_ok(enic->netdev)) + netif_carrier_off(enic->netdev); + netdev_dbg(enic->netdev, "MBOX: link state -> DOWN\n"); + break; + default: + netdev_warn(enic->netdev, "MBOX: unknown link state %u\n", + le32_to_cpu(notif->link_state)); + ack.ack.ret_major =3D cpu_to_le16(ENIC_MBOX_ERR_GENERIC); + break; + } + + enic_mbox_send_msg(enic, ENIC_MBOX_PF_LINK_STATE_ACK, ENIC_MBOX_DST_PF, + &ack, sizeof(ack)); +} + +static bool enic_mbox_vf_payload_ok(struct enic *enic, u8 msg_type, + u16 payload_len, size_t min_len) +{ + if (payload_len < min_len) { + netdev_warn(enic->netdev, + "MBOX: short payload for type %u (%u < %zu)\n", + msg_type, payload_len, min_len); + return false; + } + return true; +} + +static void enic_mbox_vf_process_msg(struct enic *enic, + struct enic_mbox_hdr *hdr, void *payload, + u16 payload_len) +{ + switch (hdr->msg_type) { + case ENIC_MBOX_VF_CAPABILITY_REPLY: { + size_t exp =3D sizeof(struct enic_mbox_vf_capability_reply_msg); + + if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type, + payload_len, exp)) + return; + enic_mbox_vf_handle_capability_reply(enic, payload); + break; + } + case ENIC_MBOX_VF_REGISTER_REPLY: { + size_t exp =3D sizeof(struct enic_mbox_vf_register_reply_msg); + + if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type, + payload_len, exp)) + return; + enic_mbox_vf_handle_register_reply(enic, payload); + break; + } + case ENIC_MBOX_VF_UNREGISTER_REPLY: { + size_t exp =3D sizeof(struct enic_mbox_vf_register_reply_msg); + + if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type, + payload_len, exp)) + return; + enic_mbox_vf_handle_unregister_reply(enic, payload); + break; + } + case ENIC_MBOX_PF_LINK_STATE_NOTIF: { + size_t exp =3D sizeof(struct enic_mbox_pf_link_state_notif_msg); + + if (!enic_mbox_vf_payload_ok(enic, hdr->msg_type, + payload_len, exp)) + return; + enic_mbox_vf_handle_link_state(enic, payload); + break; + } + default: + netdev_dbg(enic->netdev, + "MBOX: VF unhandled msg type %u\n", + hdr->msg_type); + break; + } +} + static void enic_mbox_recv_handler(struct enic *enic, void *buf, unsigned int len) { @@ -340,11 +502,105 @@ static void enic_mbox_recv_handler(struct enic *enic= , void *buf, =20 if (enic->vf_state) enic_mbox_pf_process_msg(enic, hdr, payload); + else + enic_mbox_vf_process_msg(enic, hdr, payload, + msg_len - (u16)sizeof(*hdr)); +} + +int enic_mbox_vf_capability_check(struct enic *enic) +{ + struct enic_mbox_vf_capability_msg req =3D {}; + int err; + + enic->pf_cap_version =3D 0; + enic->mbox_expected_reply =3D ENIC_MBOX_VF_CAPABILITY_REPLY; + reinit_completion(&enic->mbox_comp); + req.version =3D cpu_to_le32(ENIC_MBOX_CAP_VERSION_1); + + err =3D enic_mbox_send_msg(enic, ENIC_MBOX_VF_CAPABILITY_REQUEST, + ENIC_MBOX_DST_PF, &req, sizeof(req)); + if (err) { + enic->mbox_expected_reply =3D 0; + return err; + } + + err =3D enic_mbox_wait_reply(enic, 3000); + enic->mbox_expected_reply =3D 0; + if (err) { + netdev_warn(enic->netdev, + "MBOX: no capability reply from PF\n"); + return err; + } + + if (enic->pf_cap_version < ENIC_MBOX_CAP_VERSION_1) { + netdev_warn(enic->netdev, + "MBOX: PF version %u too old\n", + enic->pf_cap_version); + return -EOPNOTSUPP; + } + + return 0; +} + +int enic_mbox_vf_register(struct enic *enic) +{ + int err; + + enic->vf_registered =3D false; + enic->mbox_expected_reply =3D ENIC_MBOX_VF_REGISTER_REPLY; + reinit_completion(&enic->mbox_comp); + + err =3D enic_mbox_send_msg(enic, ENIC_MBOX_VF_REGISTER_REQUEST, + ENIC_MBOX_DST_PF, NULL, 0); + if (err) { + enic->mbox_expected_reply =3D 0; + return err; + } + + err =3D enic_mbox_wait_reply(enic, 3000); + enic->mbox_expected_reply =3D 0; + if (err) { + netdev_warn(enic->netdev, + "MBOX: VF registration with PF timed out\n"); + return err; + } + + if (!enic->vf_registered) + return -ENODEV; + + return 0; +} + +int enic_mbox_vf_unregister(struct enic *enic) +{ + int err; + + if (!enic->vf_registered) + return 0; + + enic->mbox_expected_reply =3D ENIC_MBOX_VF_UNREGISTER_REPLY; + reinit_completion(&enic->mbox_comp); + + err =3D enic_mbox_send_msg(enic, ENIC_MBOX_VF_UNREGISTER_REQUEST, + ENIC_MBOX_DST_PF, NULL, 0); + if (err) { + enic->mbox_expected_reply =3D 0; + return err; + } + + err =3D enic_mbox_wait_reply(enic, 3000); + enic->mbox_expected_reply =3D 0; + if (err) + return err; + if (enic->vf_registered) + return -EACCES; + return 0; } =20 void enic_mbox_init(struct enic *enic) { enic->mbox_msg_num =3D 0; mutex_init(&enic->mbox_lock); + init_completion(&enic->mbox_comp); WRITE_ONCE(enic->admin_rq_handler, enic_mbox_recv_handler); } diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.h b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.h index f1de67db1273..15e30ee2b0ed 100644 --- a/drivers/net/ethernet/cisco/enic/enic_mbox.h +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.h @@ -88,5 +88,8 @@ void enic_mbox_init(struct enic *enic); int enic_mbox_send_msg(struct enic *enic, u8 msg_type, u16 dst_vnic_id, void *payload, u16 payload_len); int enic_mbox_send_link_state(struct enic *enic, u16 vf_id, u32 link_state= ); +int enic_mbox_vf_capability_check(struct enic *enic); +int enic_mbox_vf_register(struct enic *enic); +int enic_mbox_vf_unregister(struct enic *enic); =20 #endif /* _ENIC_MBOX_H_ */ --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-8.cisco.com (alln-iport-8.cisco.com [173.37.142.95]) (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 5569E4C9009; Wed, 13 May 2026 15:16:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685375; cv=none; b=T3W+R5Ku1A6ezROHeeD2yS2lEyosQsjzBQ+wiaAEdEI+yRu1U5Rowd1geueG2I/yDGWl4mWMDqEwpgwI0SO27eUSKaM64i1OybGA7/Q40ZnbvNkgzgi687ESHl7/9z9iOFEvnfrc2+irWudnVRS9VBrjftx17jU1pXYYYsjYds0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685375; c=relaxed/simple; bh=udfFmRkoSwPuAnu3VVhPRFk0F0P/tijObG52lqyofpw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J7kRfm4MvSBWehU1L+9Sv7bkK5edYp2aRtblaXWXK3GDuDr78hAPOvQWxME5oPC6LWqohQILmIXOE+FylpkpGyhpxjSTBxsfhtCd/EA/UN00Sz0C0FRXITqQSSjEuctNfVsp9csvz1BSEB4OaK51ZG/9+CywqQOYSEJFOb46B6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=JjOth9Ad; arc=none smtp.client-ip=173.37.142.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="JjOth9Ad" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=13483; q=dns/txt; s=iport01; t=1778685373; x=1779894973; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=Cof/Y3U6FkTC9zKuqV3gUgOvlNkPfv17f3DSFuLXP74=; b=JjOth9Ad6ktSeYyAbugZP2zmx4TJFpBsNSjovuf6SC28u9AtQSIViA40 m8VPwC6GtTa9T9T4ojFph28SxBB+G44NlgxhPjF6RvC6zM/jB3JsPxzHJ a9jntnRUeTCAddWLgyEU3XZhKQlk0j1CpUP9feCnnfdyQy/cXovWxJfQR iZGDOn0ew9p/paAE7mQ1hiVg1x76hZDQhyLOWm8I2YTf+t+DQ8T1UQ7S0 k/Onz45IdIqTplyGEYJh6hXjFfKs/ESjP4RTgAnSRc1I6NDXJ7nI1RB0X NQsoNQ3ojIs4ImJS/hNNeHyTWS5N6ZlGtEwCFb/Mt10qzsjwIUBifvU62 w==; X-CSE-ConnectionGUID: mRc5k11JSfWpQSYfykGCKw== X-CSE-MsgGUID: 4PyesxIMTRGs/NWzyXmqHg== X-IPAS-Result: =?us-ascii?q?A0AnAACnlARq/5D/Ja1aHQEBAQEJARIBBQUBgXwIAQsBg?= =?us-ascii?q?hc/gVBDSYRXiByHN4Ihnh0UgWsPAQEBD1EEAQGFBgKNMgImNAkOAQIEAwIDA?= =?us-ascii?q?QEBAQEBAQEBAQELAQEFAQEBAgEHBYEOE4ZchlsCAQMjBFIQJQImAgJGEAYBE?= =?us-ascii?q?oMCgnQDswx6fzOBAYR92USBZAELFAGBCi4BhXGCZwGBcIQGO4RAJxuBSUSBF?= =?us-ascii?q?AGDaIEogwKDdIJpBIMcFI54CT+BAhwDWSwBVRMNCgsHBWFSMwMgCgsSEhgVA?= =?us-ascii?q?hQvDwQWMh1wDCcSLBczWBsHBYFLggVyFDEEIYEChF94IywDToFDAwsYDUgRL?= =?us-ascii?q?DcGDhsEPQFuB4o/HQ+BNglRGQcOSxwaB4EpDD8UHwIUXpJjBxaDYY1da4E1n?= =?us-ascii?q?1mEJoFkoA4BMoQEk2KTBZkGIoI2ogGEaIFoPIFZMxoIGxWDIlMZD44tFhx4A?= =?us-ascii?q?QLLJCcyPwcCBw4CkXMEgXkBAQ?= IronPort-Data: A9a23:QeQfg6CPCXQ4qRVW/+niw5YqxClBgxIJ4kV8jS/XYbTApDwigWAFn GBLXmuAb/vfNmXzKdAjOt+38RxSscDVyYNnOVdlrnsFo1CmBibm6XV1Cm+qYkt+++WaFBoPA /02M4eGdIZvCCeA+n9BC5C5xVFkz6aEW7HgP+DNPyF1VGdMRTwo4f5Zs7ZRbrVA357jWGthh fuo+5eBYAL8gGYtWo4pw/vrRC1H7ayaVAww5jTSVdgT1HfCmn8cCo4oJK3ZBxPQXolOE+emc P3Ixbe/83mx109F5gSNy+uTnuUiG9Y+DCDW4pZkc/HKbitq+kTe5p0G2M80Mi+7vdkmc+dZk 72hvbToIesg0zaldO41C3G0GAkmVUFKFSOuzXWX6aSuI0P6n3TExs9lUUJvZK8j9NlvOFp/+ +0bBxsucUXW7w626OrTpuhEnM8vKozveYgYoHwllW6fBvc9SpeFSKLPjTNa9G5v3YYVQrCEO pdfMGYzBPjDS0Un1lM/E5sinfyohXnXeDxDo1XTrq0yi4TW5FMtiOezboWOK7RmQ+0JpleVv XLn2ljDLQpdEuON2AqA61Kj07qncSTTHdh6+KeD3vJjnlCW7mAaFhATUVy1vb+/h1LWc99TN kkd6Ccyhac180OvQ5/2WBjQiH2ZtBc0WNdKFeA+rgaXxcL86gCVHGUbDThMdNArqucyWDosk FSJ9/vxDDZitry9U3+R9r6I6zi1PEA9KW4EeD9BTgYf5dTniJ88gwiJTdt5FqOxyNrvFlnYx T2WoCUgr6scgNRN1Kih+13DxTW2qfD0ohUd/A7bWCehqwh+foPgP9Pu4lnA5vEGJ4GcJrWcg EU5dwGlxLhmJfmweOalGY3hwJnBCy65DQDh IronPort-HdrOrdr: A9a23:MbOQH6Pohr1r6MBcTjejsMiBIKoaSvp037Dk7TEUdfUzSK2lfq GV8sjzuiWYtN98YhsdcJW7Scu9qBDnmqKdn7NwAV7KZmCP01dAbrsSjrcKqAeNJ8SRzJ856Y 5QN4VzF9H0C0F3loLZ7BnQKadY/PC3tI2lmuvayW5gVkVRa69m5xpkEQrzKDwReOA/P+tfKL OsouxaujGnZXMbKu6/BnUDQqz/guejruOfXfbDbCRXkjVnSliTmcXHLyQ= X-Talos-CUID: 9a23:oaXmOGx1R3OzeAtEK+qgBgURIMt4cSSE7kzeHFeBMldnWb66YnyPrfY= X-Talos-MUID: 9a23:zDZyVgafblZXBOBT6wf9iSpyFeJU2Yu1T2Yyg4Q2vtCkOnkl X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="740766739" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-8.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:07 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id C87A118000485; Wed, 13 May 2026 15:16:06 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:46 -0700 Subject: [PATCH net-next v7 09/10] enic: wire V2 SR-IOV enable with admin channel and MBOX 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-9-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685360; l=13859; i=satishkh@cisco.com; h=from:subject:message-id; bh=udfFmRkoSwPuAnu3VVhPRFk0F0P/tijObG52lqyofpw=; b=JO8JsJ6K9wUM2BdZb2JHq9XplBOWZrG4g/Y1S6UGbPFhnWBXzgXXc1Toe/daZTD7AKxuyzJ5d RIwtKnWHsEgD2LbA7OLdb5ql1JyUhn7AIffqCp0lRbvrRsDoT5hmnBi X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com Extend enic_sriov_configure() to handle V2 SR-IOV VFs. When the PF detects V2 VF device IDs, the enable path allocates per-VF MBOX state, opens the admin channel, initializes the MBOX protocol, and then calls pci_enable_sriov(). The admin channel must be ready before VFs are created so that VF drivers can immediately begin the MBOX capability and registration handshake during their probe. The enic_sriov_configure() dispatcher and its V2 helpers (enic_sriov_v2_enable, enic_sriov_v2_disable) are defined here but intentionally not yet wired into struct pci_driver via .sriov_configure -- hence the __maybe_unused annotations. This series introduces only the admin channel and MBOX infrastructure; sysfs-driven V2 enable/disable will be activated in a follow-up patch by adding ".sriov_configure =3D enic_sriov_configure," to enic_driver. The disable path reverses this order: pci_disable_sriov() first (so VF drivers unregister via MBOX), then the admin channel is closed and per-VF state is freed. Reject VF port profile requests when V2 SR-IOV is active (enic_is_valid_pp_vf), since enic->pp is not reallocated for V2 VFs and the V2 protocol uses MBOX instead of port profiles. Update enic_remove() to run enic_dev_deinit() and vnic_dev_close() after SR-IOV teardown, so the PF device remains functional while VFs are being cleaned up. This ordering applies to both V1 and V2 SR-IOV paths. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic.h | 1 + drivers/net/ethernet/cisco/enic/enic_admin.c | 2 + drivers/net/ethernet/cisco/enic/enic_main.c | 182 +++++++++++++++++++++++= ++-- drivers/net/ethernet/cisco/enic/enic_mbox.c | 13 +- drivers/net/ethernet/cisco/enic/enic_pp.c | 5 + drivers/net/ethernet/cisco/enic/enic_res.c | 1 + drivers/net/ethernet/cisco/enic/vnic_enet.h | 4 +- 7 files changed, 194 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/= cisco/enic/enic.h index 483053c781df..1bf7a91ad915 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -323,6 +323,7 @@ struct enic { * waiter. */ u8 mbox_expected_reply; + bool mbox_initialized; =20 /* PF: per-VF MBOX state, allocated when SRIOV V2 is enabled */ struct enic_vf_state { diff --git a/drivers/net/ethernet/cisco/enic/enic_admin.c b/drivers/net/eth= ernet/cisco/enic/enic_admin.c index 83d43e6e4d17..5eefe6fd6955 100644 --- a/drivers/net/ethernet/cisco/enic/enic_admin.c +++ b/drivers/net/ethernet/cisco/enic/enic_admin.c @@ -589,5 +589,7 @@ void enic_admin_channel_close(struct enic *enic) vnic_cq_clean(&enic->admin_cq[0]); vnic_cq_clean(&enic->admin_cq[1]); vnic_intr_clean(&enic->admin_intr); + + WRITE_ONCE(enic->admin_rq_handler, NULL); enic_admin_free_resources(enic); } diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethe= rnet/cisco/enic/enic_main.c index 53d68272d06a..65069440ec9a 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -60,6 +60,8 @@ #include "enic_clsf.h" #include "enic_rq.h" #include "enic_wq.h" +#include "enic_admin.h" +#include "enic_mbox.h" =20 #define ENIC_NOTIFY_TIMER_PERIOD (2 * HZ) =20 @@ -2155,12 +2157,35 @@ static void enic_reset(struct work_struct *work) enic_set_api_busy(enic, true); =20 enic_stop(enic->netdev); + + /* Quiesce admin channel before soft reset. The reset disables + * all hardware queues including the admin WQ/RQ; mask the admin + * interrupt, drain NAPI and work, and block further MBOX sends + * so the channel is cleanly idle when we reinitialise. + */ + if (enic_sriov_enabled(enic) && + enic->vf_type =3D=3D ENIC_VF_TYPE_V2) { + vnic_intr_mask(&enic->admin_intr); + napi_disable(&enic->admin_napi); + cancel_work_sync(&enic->admin_msg_work); + WRITE_ONCE(enic->mbox_send_disabled, true); + } + enic_dev_soft_reset(enic); enic_reset_addr_lists(enic); enic_init_vnic_resources(enic); enic_set_rss_nic_cfg(enic); enic_dev_set_ig_vlan_rewrite_mode(enic); enic_ext_cq(enic); + + /* Re-enable admin channel after reinitialising hardware */ + if (enic_sriov_enabled(enic) && + enic->vf_type =3D=3D ENIC_VF_TYPE_V2) { + WRITE_ONCE(enic->mbox_send_disabled, false); + napi_enable(&enic->admin_napi); + vnic_intr_unmask(&enic->admin_intr); + } + enic_open(enic->netdev); =20 /* Allow infiniband to fiddle with the device again */ @@ -2200,6 +2225,8 @@ static void enic_tx_hang_reset(struct work_struct *wo= rk) =20 static int enic_set_intr_mode(struct enic *enic) { + unsigned int admin_reserve =3D enic->has_admin_channel ? 1 : 0; + unsigned int min_intr =3D ENIC_MSIX_MIN_INTR + admin_reserve; unsigned int i; int num_intr; =20 @@ -2210,12 +2237,12 @@ static int enic_set_intr_mode(struct enic *enic) */ =20 if (enic->config.intr_mode < 1 && - enic->intr_avail >=3D ENIC_MSIX_MIN_INTR) { + enic->intr_avail >=3D min_intr) { for (i =3D 0; i < enic->intr_avail; i++) enic->msix_entry[i].entry =3D i; =20 num_intr =3D pci_enable_msix_range(enic->pdev, enic->msix_entry, - ENIC_MSIX_MIN_INTR, + min_intr, enic->intr_avail); if (num_intr > 0) { vnic_dev_set_intr_mode(enic->vdev, @@ -2310,7 +2337,13 @@ static int enic_adjust_resources(struct enic *enic) enic->cq_count =3D 2; enic->intr_count =3D enic->intr_avail; break; - case VNIC_DEV_INTR_MODE_MSIX: + case VNIC_DEV_INTR_MODE_MSIX: { + /* Reserve one MSI-X slot for the admin channel interrupt + * when V2 SR-IOV admin channel resources are present. + */ + unsigned int admin_reserve =3D + enic->has_admin_channel ? 1 : 0; + /* Adjust the number of wqs/rqs/cqs/interrupts that will be * used based on which resource is the most constrained */ @@ -2319,7 +2352,8 @@ static int enic_adjust_resources(struct enic *enic) ENIC_RQ_MIN_DEFAULT); rq_avail =3D min3(enic->rq_avail, ENIC_RQ_MAX, rq_default); max_queues =3D min(enic->cq_avail, - enic->intr_avail - ENIC_MSIX_RESERVED_INTR); + enic->intr_avail - ENIC_MSIX_RESERVED_INTR - + admin_reserve); if (wq_avail + rq_avail <=3D max_queues) { enic->rq_count =3D rq_avail; enic->wq_count =3D wq_avail; @@ -2337,6 +2371,7 @@ static int enic_adjust_resources(struct enic *enic) enic->intr_count =3D enic->cq_count + ENIC_MSIX_RESERVED_INTR; =20 break; + } default: dev_err(enic_get_dev(enic), "Unknown interrupt mode\n"); return -EINVAL; @@ -2689,6 +2724,124 @@ static void enic_sriov_detect_vf_type(struct enic *= enic) enic->vf_type =3D ENIC_VF_TYPE_NONE; } } + +static int __maybe_unused +enic_sriov_v2_enable(struct enic *enic, int num_vfs) +{ + int err; + + if (!enic->has_admin_channel) { + netdev_err(enic->netdev, + "V2 SR-IOV requires admin channel resources\n"); + return -EOPNOTSUPP; + } + + enic->vf_state =3D kcalloc(num_vfs, sizeof(*enic->vf_state), GFP_KERNEL); + if (!enic->vf_state) + return -ENOMEM; + + err =3D enic_admin_channel_open(enic); + if (err) { + netdev_err(enic->netdev, + "Failed to open admin channel: %d\n", err); + goto free_vf_state; + } + + enic_mbox_init(enic); + + enic->num_vfs =3D num_vfs; + + err =3D pci_enable_sriov(enic->pdev, num_vfs); + if (err) { + netdev_err(enic->netdev, + "pci_enable_sriov failed: %d\n", err); + goto close_admin; + } + + enic->priv_flags |=3D ENIC_SRIOV_ENABLED; + return num_vfs; + +close_admin: + enic->num_vfs =3D 0; + enic_admin_channel_close(enic); +free_vf_state: + kfree(enic->vf_state); + enic->vf_state =3D NULL; + return err; +} + +static void enic_sriov_v2_disable(struct enic *enic) +{ + pci_disable_sriov(enic->pdev); + enic_admin_channel_close(enic); + kfree(enic->vf_state); + enic->vf_state =3D NULL; + enic->num_vfs =3D 0; + enic->priv_flags &=3D ~ENIC_SRIOV_ENABLED; +} + +static int __maybe_unused +enic_sriov_configure(struct pci_dev *pdev, int num_vfs) +{ + struct net_device *netdev =3D pci_get_drvdata(pdev); + struct enic *enic =3D netdev_priv(netdev); + struct enic_port_profile *pp; + int err; + + if (num_vfs > 0) { + if (enic->config.mq_subvnic_count) { + netdev_err(netdev, + "SR-IOV not supported with multi-queue sub-vnics\n"); + return -EOPNOTSUPP; + } + + if (enic->vf_type =3D=3D ENIC_VF_TYPE_NONE) { + netdev_err(netdev, + "SR-IOV not supported on this firmware version\n"); + return -EOPNOTSUPP; + } + + if (enic->vf_type =3D=3D ENIC_VF_TYPE_V2) + return enic_sriov_v2_enable(enic, num_vfs); + + pp =3D kcalloc(num_vfs, sizeof(*pp), GFP_KERNEL); + if (!pp) + return -ENOMEM; + + err =3D pci_enable_sriov(pdev, num_vfs); + if (err) { + kfree(pp); + return err; + } + + kfree(enic->pp); + enic->pp =3D pp; + enic->num_vfs =3D num_vfs; + enic->priv_flags |=3D ENIC_SRIOV_ENABLED; + return num_vfs; + } + + if (!enic_sriov_enabled(enic)) + return 0; + + if (enic->vf_type =3D=3D ENIC_VF_TYPE_V2) { + enic_sriov_v2_disable(enic); + return 0; + } + + pp =3D kzalloc_obj(*enic->pp, GFP_KERNEL); + if (!pp) + return -ENOMEM; + + pci_disable_sriov(pdev); + enic->num_vfs =3D 0; + enic->priv_flags &=3D ~ENIC_SRIOV_ENABLED; + + kfree(enic->pp); + enic->pp =3D pp; + + return 0; +} #endif =20 static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *en= t) @@ -2787,12 +2940,18 @@ static int enic_probe(struct pci_dev *pdev, const s= truct pci_device_id *ent) goto err_out_vnic_unregister; =20 #ifdef CONFIG_PCI_IOV - /* Get number of subvnics */ + enic_sriov_detect_vf_type(enic); + + /* Auto-enable SR-IOV if VFs were pre-configured (e.g. at boot). + * V2 VFs require the admin channel, which is not yet set up at probe + * time; use sysfs (enic_sriov_configure) to enable V2 SR-IOV instead. + */ pos =3D pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); if (pos) { pci_read_config_word(pdev, pos + PCI_SRIOV_TOTAL_VF, &enic->num_vfs); - if (enic->num_vfs) { + if (enic->num_vfs && + enic->vf_type !=3D ENIC_VF_TYPE_V2) { err =3D pci_enable_sriov(pdev, enic->num_vfs); if (err) { dev_err(dev, "SRIOV enable failed, aborting." @@ -2804,7 +2963,6 @@ static int enic_probe(struct pci_dev *pdev, const str= uct pci_device_id *ent) num_pps =3D enic->num_vfs; } } - enic_sriov_detect_vf_type(enic); #endif =20 /* Allocate structure for port profiles */ @@ -3033,14 +3191,16 @@ static void enic_remove(struct pci_dev *pdev) cancel_work_sync(&enic->reset); cancel_work_sync(&enic->change_mtu_work); unregister_netdev(netdev); - enic_dev_deinit(enic); - vnic_dev_close(enic->vdev); #ifdef CONFIG_PCI_IOV if (enic_sriov_enabled(enic)) { - pci_disable_sriov(pdev); - enic->priv_flags &=3D ~ENIC_SRIOV_ENABLED; + if (enic->vf_type =3D=3D ENIC_VF_TYPE_V2) + enic_sriov_v2_disable(enic); + else + pci_disable_sriov(pdev); } #endif + enic_dev_deinit(enic); + vnic_dev_close(enic->vdev); kfree(enic->pp); vnic_dev_unregister(enic->vdev); enic_iounmap(enic); diff --git a/drivers/net/ethernet/cisco/enic/enic_mbox.c b/drivers/net/ethe= rnet/cisco/enic/enic_mbox.c index b555362379b3..fb656327a874 100644 --- a/drivers/net/ethernet/cisco/enic/enic_mbox.c +++ b/drivers/net/ethernet/cisco/enic/enic_mbox.c @@ -599,8 +599,17 @@ int enic_mbox_vf_unregister(struct enic *enic) =20 void enic_mbox_init(struct enic *enic) { + /* mbox_lock and mbox_comp must be initialized exactly once per + * device lifetime; the PF sriov_configure path can re-enter this + * on each enable cycle where these primitives are already set up. + */ + if (!enic->mbox_initialized) { + mutex_init(&enic->mbox_lock); + init_completion(&enic->mbox_comp); + enic->mbox_initialized =3D true; + } else { + reinit_completion(&enic->mbox_comp); + } enic->mbox_msg_num =3D 0; - mutex_init(&enic->mbox_lock); - init_completion(&enic->mbox_comp); WRITE_ONCE(enic->admin_rq_handler, enic_mbox_recv_handler); } diff --git a/drivers/net/ethernet/cisco/enic/enic_pp.c b/drivers/net/ethern= et/cisco/enic/enic_pp.c index 4720a952725d..3f611e240c25 100644 --- a/drivers/net/ethernet/cisco/enic/enic_pp.c +++ b/drivers/net/ethernet/cisco/enic/enic_pp.c @@ -25,6 +25,11 @@ int enic_is_valid_pp_vf(struct enic *enic, int vf, int *= err) if (vf !=3D PORT_SELF_VF) { #ifdef CONFIG_PCI_IOV if (enic_sriov_enabled(enic)) { + /* V2 SR-IOV uses MBOX, not port profiles */ + if (enic->vf_type =3D=3D ENIC_VF_TYPE_V2) { + *err =3D -EOPNOTSUPP; + goto err_out; + } if (vf < 0 || vf >=3D enic->num_vfs) { *err =3D -EINVAL; goto err_out; diff --git a/drivers/net/ethernet/cisco/enic/enic_res.c b/drivers/net/ether= net/cisco/enic/enic_res.c index 2b7545d6a67f..436326ace049 100644 --- a/drivers/net/ethernet/cisco/enic/enic_res.c +++ b/drivers/net/ethernet/cisco/enic/enic_res.c @@ -59,6 +59,7 @@ int enic_get_vnic_config(struct enic *enic) GET_CONFIG(intr_timer_usec); GET_CONFIG(loop_tag); GET_CONFIG(num_arfs); + GET_CONFIG(mq_subvnic_count); GET_CONFIG(max_rq_ring); GET_CONFIG(max_wq_ring); GET_CONFIG(max_cq_ring); diff --git a/drivers/net/ethernet/cisco/enic/vnic_enet.h b/drivers/net/ethe= rnet/cisco/enic/vnic_enet.h index 9e8e86262a3f..519d2969990b 100644 --- a/drivers/net/ethernet/cisco/enic/vnic_enet.h +++ b/drivers/net/ethernet/cisco/enic/vnic_enet.h @@ -21,7 +21,9 @@ struct vnic_enet_config { u16 loop_tag; u16 vf_rq_count; u16 num_arfs; - u8 reserved[66]; + u8 reserved1[32]; + u16 mq_subvnic_count; + u8 reserved2[32]; u32 max_rq_ring; // MAX RQ ring size u32 max_wq_ring; // MAX WQ ring size u32 max_cq_ring; // MAX CQ ring size --=20 2.43.0 From nobody Fri Jun 12 17:20:21 2026 Received: from alln-iport-5.cisco.com (alln-iport-5.cisco.com [173.37.142.92]) (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 8D8FB4CA282; Wed, 13 May 2026 15:16:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=173.37.142.92 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685376; cv=none; b=AonlTixeYxR/EvIxiHl+Iaa/bq5xcxy/6fxPZ1BpB5TM/48Dr5scs6s7sIHXqor77ziRe6AvRMwrnPVYkIhbGgV/iuvtpw6oguJzPJruPAf2pbk4c1ZSDJkpfepzlbk1xOtTO956Pm6ruiQk04XFeokjfG7O26SSwwIx7Tu4Txo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778685376; c=relaxed/simple; bh=zzkYcyXi6N69CSiuCx09RarocX/ENESP+V0rdeC6Ydc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=D0BDDl1rNDmrKH4aKy2Xvznef9lO8w8RChPM50hGMZR5dkiA7PIfh/glvGHWUmrDigHZa2UV9MLg/tBXVahUamW5zPLfQRykWM2lJdbNcWgo8JNM9bJ2uTOxoSLH/F89YoeV+Um6A33aU5aiUlQq1Gbc91k26r3gMsgk6svRugo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com; spf=pass smtp.mailfrom=cisco.com; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b=DHy2uowo; arc=none smtp.client-ip=173.37.142.92 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=cisco.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=cisco.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cisco.com header.i=@cisco.com header.b="DHy2uowo" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cisco.com; i=@cisco.com; l=7725; q=dns/txt; s=iport01; t=1778685374; x=1779894974; h=from:date:subject:mime-version:content-transfer-encoding: message-id:references:in-reply-to:to:cc; bh=Eium11uD/vJCWWRYbHBfyGh7Si/SPzpgsVZKctkORY4=; b=DHy2uowohEsC7k1pGs3nKY6AOvZxpx3tQXLoB5bx+lh5CcvqtEJEWD3n O+kQWd4jg+vyW5hvfe7YJBWJjrDgeY6DGke7YCy2n1/XBk9KTKk3crjA6 e7p/ZYA82id1+tHwFN/rH9Ura6nnyJ3dxPJcLWpVXzmCu1NuT1OFVZXop b4RP1UJXjTyJ5oQOgcQVNCLmAGDk79UdUCxIBkGw2GeRwQni3y9LoY+L3 tp/vx9JOkoJ4WhXhtWn6CLvnu6aUype82WsOrc7eMhVNsGcBdV0hOnE8S 6s6lUKRIS2gQtcWt4sKeSax+4OIumPPdvlStROw3rKPewPl6jGdEdQlbQ A==; X-CSE-ConnectionGUID: i1nv6s03QLaLaxr9yzdrpg== X-CSE-MsgGUID: ojrpSLW7S2CLpSPSCqK2LQ== X-IPAS-Result: =?us-ascii?q?A0BFAgAclARq/5D/Ja1aglmCV4FQQ0mEV49TgiGeHRSBa?= =?us-ascii?q?w8BAQEPUQQBAYUGAo0yAiY0CQ4BAgQDAgMBAQEBAQEBAQEBAQsBAQUBAQECA?= =?us-ascii?q?QcFgQ4ThlyGWwIBAyMEUhAlAiYCAkYQBgESgwKCdAOzDHp/M4EBhH3ZRIFkA?= =?us-ascii?q?QsUAYEKLoVygmcBgXCEBjuEQCcbgUlEgRQBgnlvhAUlg3SCaQSCDYEPFI54C?= =?us-ascii?q?T+BAhwDWSwBVRMNCgsHBWFSMwMgCgsSEhgVAhQcEw8EFjIdcAwnEiwXM1gbB?= =?us-ascii?q?wWBS4IFchQxBCGBAoRfeCMsA06BQwMLGA1IESw3Bg4bBD0BbgeKPx0PgT0BA?= =?us-ascii?q?WoHAYEOQjkyAwwyJRUILQmTH4N+jV1rgTWfWYQmgWSgDgEyl2aTBZkGIqNeW?= =?us-ascii?q?YRogWg8gVkzGggbFYMiUxkPji0WHMwfJzI/BwIHDgKRcwSBeQEB?= IronPort-Data: A9a23:Lboog68Fm3jeFeSVog+KDrUDQH+TJUtcMsCJ2f8bNWPcYEJGY0x3y zFMDD+FP/rbNjD2LdFyPNvjo04B7MDdmNE2GQA4rSBEQiMRo6IpJzg2wmQcns+2BpeeJK6yx 5xGMrEsFOhtEDmE4EzrauS9xZVF/fngbqLmD+LZMTxGSwZhSSMw4TpugOdRbrRA2bBVOCvT/ 4mpyyHjEAX9gWAsbztPs/vrRC5H5ZwehhtJ5jTSWtgT1LPuvyF9JI4SI6i3M0z5TuF8dsamR /zOxa2O5WjQ+REgELuNyt4XpWVTH9Y+lSDX4pZnc/DKbipq/0Te4Y5nXBYoUnq7vh3S9zxHJ HqhgrTrIeshFvWkdO3wyHC0GQkmVUFN0OevzXRSLaV/wmWeG0YAzcmCA2k3ZIsGpP0vWlhq/ NgROCpcfwKPnfq5lefTpulE3qzPLeHxN48Z/3UlxjbDALN+HtbIQr7B4plT2zJYasJmRKmFI ZFGL2AyMVKZP0En1lQ/UPrSmM+zj2X+aD1bqHqepLE85C7YywkZPL3Fb4aMI4bQHJUN9qqej mXE5XzCJi5FD4a07SK+ykmHn8yVuRquDer+E5X9rJaGmma7ymUNBRg+WVKlrPy9jUCiHdRSN yQ89yYzqKEg+VCDQd76UBm15nWDu3Y0WMdaGsU55RuLx66S5ByWbkANSDJbZcNlssIqSTE0/ luUmdWvDjwHmKWcQ3+b95+OoD+yMDRTJmgHDQcATA0Y85zgrZs1gxbnUNluCui2g8fzFDW2x CqFxAA4iqkfgNAjyaq25xbEjiiqq5yPSRQ6jjg7RUq/5Q9/IYrgbIuy5B2DsrBLLZ2SSR+Ku 31sd9Wi0d3ixKqlzESlKNjh1pnwjxpZGFUwWWJSIqQ= IronPort-HdrOrdr: A9a23:J01KUKnkCsniuXrtdbtcBVnn2/jpDfLa3DAbv31ZSRFFG/FwWf re+MjzsiWUtN9xYh8dcL+7VZVoLUm3yXcx2/hyAV7AZmbbURWTTL2KhLGKq1bd8m/Fh41gPM xbH5SWZueAaGRSvILW7Ba1FtA4zMLC0qy57N2utktFfEVGZ75t6gFhBh3eKE15QwFaGYE0fa DsgPav3wDQHkg/X4CcGmQPWfTFqpngkZLrZgNDOjscgTP+9Q9BLNXBYmKlNtB0aUI1/Ysf X-Talos-CUID: 9a23:Ml40ymyzizoqBgwbURH+BgUVQ8Y7LGaFl070KmuxGXw4Wa+ZU0efrfY= X-Talos-MUID: =?us-ascii?q?9a23=3AdS+aaA3BUuQN+VNNkqabeNEv1jUj5Ka0EHsprso?= =?us-ascii?q?94eKgLRdIAByEr26Te9py?= X-IronPort-Anti-Spam-Filtered: true X-IronPort-AV: E=Sophos;i="6.23,232,1770595200"; d="scan'208";a="741122180" Received: from rcdn-l-core-07.cisco.com ([173.37.255.144]) by alln-iport-5.cisco.com with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 13 May 2026 15:16:08 +0000 Received: from [127.0.0.1] (unknown [10.25.128.216]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by rcdn-l-core-07.cisco.com (Postfix) with ESMTPS id 881321800048A; Wed, 13 May 2026 15:16:07 +0000 (GMT) From: Satish Kharat Date: Wed, 13 May 2026 08:15:47 -0700 Subject: [PATCH net-next v7 10/10] enic: add V2 VF probe with admin channel and PF registration 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: <20260513-enic-sriov-v2-admin-channel-v2-v7-10-68b9f4141f4c@cisco.com> References: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> In-Reply-To: <20260513-enic-sriov-v2-admin-channel-v2-v7-0-68b9f4141f4c@cisco.com> To: Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Sesidhar Baddela , Satish Kharat X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1778685360; l=7955; i=satishkh@cisco.com; h=from:subject:message-id; bh=zzkYcyXi6N69CSiuCx09RarocX/ENESP+V0rdeC6Ydc=; b=SZUcx9eUloaOpP5x6FWzndEmabCTJmruWiA9lqndiDJS41VP2xdIbeFXupfS9cK7uG1wZaO/z UPw1ybM2UUnAD0IXswKxDPhUySLrjaGwRH2AvOxXgoc5T3l+oIsadRH X-Developer-Key: i=satishkh@cisco.com; a=ed25519; pk=4BxbLoCGvHeIMH/PbpiNVx8/2IcTjFvqcr0AD8K6WLY= X-Outbound-Client-TLS: ANONYMOUS;unknown [10.25.128.216];TLSv1.3;TLS_AES_256_GCM_SHA384;256 X-Outbound-SMTP-Client: 10.25.128.216, [10.25.128.216] X-Outbound-Node: rcdn-l-core-07.cisco.com When a V2 SR-IOV VF probes, open the admin channel, initialize the MBOX protocol, perform the capability check with the PF, and register with the PF. This establishes the PF-VF communication path that the PF uses to send link state notifications. The admin channel and MBOX registration happen after enic_dev_init() (which discovers admin channel resources) and before register_netdev() so the VF is fully initialized before the interface is visible to userspace. The admin channel is opened before enic_mbox_init() installs the receive handler. This is safe because enic_admin_rq_cq_service() checks admin_rq_handler before enqueuing received buffers, so any interrupt that fires between open and mbox_init is harmlessly discarded. On remove, the VF unregisters from the PF and closes its admin channel before tearing down data path resources. V2 VFs are not provisioned with an RES_TYPE_SRIOV_INTR resource by firmware, so bypass that check in the admin channel capability detection for V2 VFs. The PF still requires this resource. Reserve an additional MSI-X interrupt for the admin channel when has_admin_channel is set in enic_set_intr_mode() and enic_adjust_resources(), so enic_admin_setup_intr()'s intr_index =3D intr_count slot is guaranteed to be within intr_avail bounds even at maximum queue configurations. The admin INTR uses a RES_TYPE_INTR_CTRL slot shared with the data path. Signed-off-by: Satish Kharat --- drivers/net/ethernet/cisco/enic/enic.h | 1 + drivers/net/ethernet/cisco/enic/enic_main.c | 88 +++++++++++++++++++++++++= +--- drivers/net/ethernet/cisco/enic/enic_res.c | 3 +- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/cisco/enic/enic.h b/drivers/net/ethernet/= cisco/enic/enic.h index 1bf7a91ad915..89cf412cec1d 100644 --- a/drivers/net/ethernet/cisco/enic/enic.h +++ b/drivers/net/ethernet/cisco/enic/enic.h @@ -450,6 +450,7 @@ void enic_reset_addr_lists(struct enic *enic); int enic_sriov_enabled(struct enic *enic); int enic_is_valid_vf(struct enic *enic, int vf); int enic_is_dynamic(struct enic *enic); +int enic_is_sriov_vf_v2(struct enic *enic); void enic_set_ethtool_ops(struct net_device *netdev); int __enic_set_rsskey(struct enic *enic); void enic_ext_cq(struct enic *enic); diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethe= rnet/cisco/enic/enic_main.c index 65069440ec9a..594c67d86e57 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -316,6 +316,11 @@ static int enic_is_sriov_vf(struct enic *enic) enic->pdev->device =3D=3D PCI_DEVICE_ID_CISCO_VIC_ENET_VF_V2; } =20 +int enic_is_sriov_vf_v2(struct enic *enic) +{ + return enic->pdev->device =3D=3D PCI_DEVICE_ID_CISCO_VIC_ENET_VF_V2; +} + int enic_is_valid_vf(struct enic *enic, int vf) { #ifdef CONFIG_PCI_IOV @@ -2338,15 +2343,19 @@ static int enic_adjust_resources(struct enic *enic) enic->intr_count =3D enic->intr_avail; break; case VNIC_DEV_INTR_MODE_MSIX: { - /* Reserve one MSI-X slot for the admin channel interrupt - * when V2 SR-IOV admin channel resources are present. - */ - unsigned int admin_reserve =3D - enic->has_admin_channel ? 1 : 0; - /* Adjust the number of wqs/rqs/cqs/interrupts that will be - * used based on which resource is the most constrained + * used based on which resource is the most constrained. + * Reserve one extra MSI-X slot for the admin channel INTR + * when has_admin_channel is set so that + * enic_admin_setup_intr() can allocate at intr_count + * within the intr_avail bounds even when the data queue + * count is maxed out. intr_count counts only the data-path + * IRQs (registered by enic_request_intr()); the admin INTR + * lives at msix index intr_count and is set up later by + * enic_admin_setup_intr(). */ + unsigned int admin_reserve =3D enic->has_admin_channel ? 1 : 0; + wq_avail =3D min(enic->wq_avail, ENIC_WQ_MAX); rq_default =3D max(netif_get_num_default_rss_queues(), ENIC_RQ_MIN_DEFAULT); @@ -3027,6 +3036,38 @@ static int enic_probe(struct pci_dev *pdev, const st= ruct pci_device_id *ent) goto err_out_dev_close; } =20 + /* V2 VF: open admin channel and register with PF. + * Must happen before register_netdev so the VF is fully + * initialized before the interface is visible to userspace. + * + * admin_channel_open() runs before enic_mbox_init() installs + * the receive handler. This is safe because + * enic_admin_rq_cq_service() checks admin_rq_handler before + * enqueuing any received buffer, so interrupts that fire + * between open and mbox_init are harmlessly discarded. + */ + if (enic_is_sriov_vf_v2(enic)) { + err =3D enic_admin_channel_open(enic); + if (err) { + dev_err(dev, + "Failed to open admin channel: %d\n", err); + goto err_out_dev_deinit; + } + enic_mbox_init(enic); + err =3D enic_mbox_vf_capability_check(enic); + if (err) { + dev_err(dev, + "MBOX capability check failed: %d\n", err); + goto err_out_admin_close; + } + err =3D enic_mbox_vf_register(enic); + if (err) { + dev_err(dev, + "MBOX VF registration failed: %d\n", err); + goto err_out_admin_close; + } + } + netif_set_real_num_tx_queues(netdev, enic->wq_count); netif_set_real_num_rx_queues(netdev, enic->rq_count); =20 @@ -3051,7 +3092,7 @@ static int enic_probe(struct pci_dev *pdev, const str= uct pci_device_id *ent) err =3D enic_set_mac_addr(netdev, enic->mac_addr); if (err) { dev_err(dev, "Invalid MAC address, aborting\n"); - goto err_out_dev_deinit; + goto err_out_admin_close; } =20 enic->tx_coalesce_usecs =3D enic->config.intr_timer_usec; @@ -3149,11 +3190,23 @@ static int enic_probe(struct pci_dev *pdev, const s= truct pci_device_id *ent) err =3D register_netdev(netdev); if (err) { dev_err(dev, "Cannot register net device, aborting\n"); - goto err_out_dev_deinit; + goto err_out_admin_close; } =20 return 0; =20 +err_out_admin_close: + if (enic_is_sriov_vf_v2(enic)) { + if (enic->vf_registered) { + int unreg_err =3D enic_mbox_vf_unregister(enic); + + if (unreg_err) + netdev_warn(netdev, + "Failed to unregister from PF: %d\n", + unreg_err); + } + enic_admin_channel_close(enic); + } err_out_dev_deinit: enic_dev_deinit(enic); err_out_dev_close: @@ -3190,6 +3243,23 @@ static void enic_remove(struct pci_dev *pdev) =20 cancel_work_sync(&enic->reset); cancel_work_sync(&enic->change_mtu_work); + + /* Close the admin channel and unregister from the PF before + * unregister_netdev() to prevent a late PF notification from + * touching a netdev that has been freed. + */ + if (enic_is_sriov_vf_v2(enic)) { + if (enic->vf_registered) { + int unreg_err =3D enic_mbox_vf_unregister(enic); + + if (unreg_err) + netdev_warn(netdev, + "Failed to unregister from PF: %d\n", + unreg_err); + } + enic_admin_channel_close(enic); + } + unregister_netdev(netdev); #ifdef CONFIG_PCI_IOV if (enic_sriov_enabled(enic)) { diff --git a/drivers/net/ethernet/cisco/enic/enic_res.c b/drivers/net/ether= net/cisco/enic/enic_res.c index 436326ace049..74cd2ee3af5c 100644 --- a/drivers/net/ethernet/cisco/enic/enic_res.c +++ b/drivers/net/ethernet/cisco/enic/enic_res.c @@ -211,7 +211,8 @@ void enic_get_res_counts(struct enic *enic) vnic_dev_get_res_count(enic->vdev, RES_TYPE_ADMIN_RQ) >=3D 1 && vnic_dev_get_res_count(enic->vdev, RES_TYPE_ADMIN_CQ) >=3D ARRAY_SIZE(enic->admin_cq) && - vnic_dev_get_res_count(enic->vdev, RES_TYPE_SRIOV_INTR) >=3D 1; + (enic_is_sriov_vf_v2(enic) || + vnic_dev_get_res_count(enic->vdev, RES_TYPE_SRIOV_INTR) >=3D 1); =20 dev_info(enic_get_dev(enic), "vNIC resources avail: wq %d rq %d cq %d intr %d admin %s\n", --=20 2.43.0