From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.11]) (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 3F88E56E04A for ; Thu, 15 Oct 2026 18:55:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.11 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792090549; cv=none; b=q7kYyVE7CzXploB7r4jo2NzB11jia6R+0XejS4HWsmH8nibmo5WM0avG4zD7tK7DyWQk99ObapP7YjknLKJBI4xCInhxmu60PiZPeARwKHGE8L7ZdQZuwRQmLJm89Px8kj0n2SvyzQnBnR/7r+SEDQlGkPzlcVXnbC/50uLEtz0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792090549; c=relaxed/simple; bh=rLAEhLqJxZ30rK0aJgkA6IlwJi2lBB/5Yr3RB3Nlamk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l9TSp8WTScY6ib/e9pLtquy7VFoJRAFW52R3CmALp78KD/Tn5DIX4MeQE5a3iNrnFESfB8nZXA5kv2hsyabFd8gq80OhOLIkjEvx0R+5lH1FA1yj0JMvp+zIrReVo8Pw3JUj+RdRBEKb+vJLBmQsaAqjXx+Tf0q1ZcJcnzOzAQc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=UDK0YzjJ; arc=none smtp.client-ip=198.175.65.11 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UDK0YzjJ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1792090541; x=1823626541; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=rLAEhLqJxZ30rK0aJgkA6IlwJi2lBB/5Yr3RB3Nlamk=; b=UDK0YzjJYE/cEQ5Eh9bu3ip+sfHmf29+WWQiHv6OTPBVQ21s+2zxrSNA /+Ko6CarPlMIyeQrUI84wF7f22cGFOKJ/4bCOI9kbMUP0PpUku5Io1Dgz R4QmI3r+gc4Z1bI98ZvtSjw/l7yIf+NKvqD/ZmLmeLiGrQaQPsGA6sGRI mLE/1kuXFCv5cXYYNMJJZcYRVlMcn7PyRPE9hyKiyZvx1xksBED7rdKBo GzUnX7V1osf6ZlawyWO4Eh4YAmfEUHMYzKCzRjJ54DhVFu9WYK7eZLx5+ rRIxcE242uGz+paFdLWj2LMl95XUnULPy+5gvAGC+uwRu8O1kS2LnEymH A==; X-CSE-ConnectionGUID: QevdBTYJRKuDhrTm5vQW/g== X-CSE-MsgGUID: HpuKOI1NTQa1fMfbnZyXAA== X-IronPort-AV: E=McAfee;i="6800,10657,11936"; a="758058" X-IronPort-AV: E=Sophos;i="6.27,160,1787036400"; d="scan'208";a="758058" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Oct 2026 11:55:33 -0700 X-CSE-ConnectionGUID: LpGD+FYATbCXc/YTUT1naA== X-CSE-MsgGUID: hf1/N+vMSRycjF1Wy00mvg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.27,160,1787036400"; d="scan'208";a="2003180" Received: from irvmail002.ir.intel.com ([10.43.11.120]) by fmviesa001.fm.intel.com with ESMTP; 15 Oct 2026 11:55:27 -0700 Received: from pkitszel-desk.tendawifi.com (unknown [10.245.244.208]) by irvmail002.ir.intel.com (Postfix) with ESMTP id 5C43E32EC8; Thu, 15 Oct 2026 19:55:25 +0100 (IST) From: Przemek Kitszel To: netdev@vger.kernel.org Cc: Tony Nguyen , Aleksandr Loktionov , Michal Schmidt , Jakub Kicinski , edumazet@kernel.org, horms@kernel.org, pabeni@redhat.com, davem@davemloft.net, Jiri Pirko , Jonathan Corbet , skhan@linuxfoundation.org, rdunlap@infradead.org, andrew+netdev@lunn.ch, saeedm@nvidia.com, tariqt@nvidia.com, leon@kernel.org, mbloch@nvidia.com, jacob.e.keller@intel.com, jedrzej.jagielski@intel.com, anzaki@gmail.com, brett.creeley@amd.com, jtornosm@redhat.com, ohartoov@nvidia.com, Przemek Kitszel Subject: [PATCH net-next v3 11/15] ice: introduce handling of virtchnl LARGE VF opcodes Date: Thu, 15 Oct 2026 20:51:22 +0200 Message-ID: <20261015185454.6332-12-przemyslaw.kitszel@intel.com> X-Mailer: git-send-email 2.51.1 In-Reply-To: <20261015185454.6332-1-przemyslaw.kitszel@intel.com> References: <20261015185454.6332-1-przemyslaw.kitszel@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Brett Creeley With new virtchnl offload/capability VFs are able to make use of more than 16 queues. But the old opcodes were designed with a max of 16 queues, so new ones were added (by iavf/virtchnl commit of this series). Handle VIRTCHNL_OP_ENABLE_QUEUES_V2, VIRTCHNL_OP_DISABLE_QUEUES_V2 and VIRTCHNL_OP_MAP_QUEUE_VECTOR here. VIRTCHNL_OP_GET_MAX_RSS_QREGION is only allowlisted, its handler comes with bigger RSS LUT support later in the series. If a VF wishes to request >16 queues it should first make sure that the PF supports the VIRTCHNL_VF_LARGE_NUM_QPAIRS capability. Signed-off-by: Brett Creeley Co-developed-by: Aleksandr Loktionov # msglen val Signed-off-by: Aleksandr Loktionov Co-developed-by: Przemek Kitszel Signed-off-by: Przemek Kitszel --- v3: * reject VIRTCHNL_OP_MAP_QUEUE_VECTOR entries with an out of range itr_idx (me) v2: * fix error response in one case of ice_vc_map_q_vector_msg() (Alex) * use ice_get_vf_vsi() instead of plain array access (Sashiko) * return VIRTCHNL_STATUS_ERR_PARAM on error (Sashiko) * commit message: GET_MAX_RSS_QREGION is handled only later --- drivers/net/ethernet/intel/ice/ice_vf_lib.h | 1 + drivers/net/ethernet/intel/ice/virt/queues.h | 3 + .../net/ethernet/intel/ice/virt/allowlist.c | 8 + drivers/net/ethernet/intel/ice/virt/queues.c | 318 ++++++++++++++++++ 4 files changed, 330 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.h b/drivers/net/ethernet/intel/ice/ice_vf_lib.h index a9e95c85bc98..396dfb2b2d97 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.h @@ -125,6 +125,7 @@ struct ice_vf_ops { void (*clear_reset_trigger)(struct ice_vf *vf); void (*irq_close)(struct ice_vf *vf); void (*post_vsi_rebuild)(struct ice_vf *vf); + struct ice_q_vector *(*get_q_vector)(struct ice_vsi *vsi, u16 vec_id); }; /* Virtchnl/SR-IOV config info */ diff --git a/drivers/net/ethernet/intel/ice/virt/queues.h b/drivers/net/ethernet/intel/ice/virt/queues.h index c4a792cecea1..223f609dd4f3 100644 --- a/drivers/net/ethernet/intel/ice/virt/queues.h +++ b/drivers/net/ethernet/intel/ice/virt/queues.h @@ -16,5 +16,8 @@ int ice_vc_cfg_q_bw(struct ice_vf *vf, u8 *msg); int ice_vc_cfg_q_quanta(struct ice_vf *vf, u8 *msg); int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg); int ice_vc_request_qs_msg(struct ice_vf *vf, u8 *msg); +int ice_vc_ena_qs_v2_msg(struct ice_vf *vf, u8 *msg, u16 msglen); +int ice_vc_dis_qs_v2_msg(struct ice_vf *vf, u8 *msg, u16 msglen); +int ice_vc_map_q_vector_msg(struct ice_vf *vf, u8 *msg, u16 msglen); #endif /* _ICE_VIRT_QUEUES_H_ */ diff --git a/drivers/net/ethernet/intel/ice/virt/allowlist.c b/drivers/net/ethernet/intel/ice/virt/allowlist.c index a07efec19c45..ef769b843c6f 100644 --- a/drivers/net/ethernet/intel/ice/virt/allowlist.c +++ b/drivers/net/ethernet/intel/ice/virt/allowlist.c @@ -95,6 +95,13 @@ static const u32 tc_allowlist_opcodes[] = { VIRTCHNL_OP_CONFIG_QUANTA, }; +static const u32 large_num_qpairs_allowlist_opcodes[] = { + VIRTCHNL_OP_GET_MAX_RSS_QREGION, + VIRTCHNL_OP_ENABLE_QUEUES_V2, + VIRTCHNL_OP_DISABLE_QUEUES_V2, + VIRTCHNL_OP_MAP_QUEUE_VECTOR, +}; + struct allowlist_opcode_info { const u32 *opcodes; size_t size; @@ -117,6 +124,7 @@ static const struct allowlist_opcode_info allowlist_opcodes[] = { ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_VLAN_V2, vlan_v2_allowlist_opcodes), ALLOW_ITEM(VIRTCHNL_VF_OFFLOAD_QOS, tc_allowlist_opcodes), ALLOW_ITEM(VIRTCHNL_VF_CAP_PTP, ptp_allowlist_opcodes), + ALLOW_ITEM(VIRTCHNL_VF_LARGE_NUM_QPAIRS, large_num_qpairs_allowlist_opcodes), }; /** diff --git a/drivers/net/ethernet/intel/ice/virt/queues.c b/drivers/net/ethernet/intel/ice/virt/queues.c index 7f2b459dbc83..4f72b6d9799f 100644 --- a/drivers/net/ethernet/intel/ice/virt/queues.c +++ b/drivers/net/ethernet/intel/ice/virt/queues.c @@ -1046,3 +1046,321 @@ int ice_vc_request_qs_msg(struct ice_vf *vf, u8 *msg) v_ret, (u8 *)vfres, sizeof(*vfres)); } +static bool ice_vc_supported_queue_type(s32 queue_type) +{ + return queue_type == VIRTCHNL_QUEUE_TYPE_RX || + queue_type == VIRTCHNL_QUEUE_TYPE_TX; +} + +/** + * ice_vc_validate_qs_v2_msg - validate all qs_msg parameters + * @vf: VF the message was received from + * @qs_msg: contents of the message from the VF + * @msglen: length of @qs_msg + * + * Used to validate both the VIRTCHNL_OP_ENABLE_QUEUES_V2 and + * VIRTCHNL_OP_DISABLE_QUEUES_V2 messages. This should always be called before + * attempting to enable and/or disable queues on behalf of a VF in response to + * the previously mentioned opcodes. + * + * Return: If all checks succeed, then return true. Otherwise return + * false, indicating to the caller that the qs_msg is invalid. + */ +static bool ice_vc_validate_qs_v2_msg(struct ice_vf *vf, + struct virtchnl_del_ena_dis_queues *qs_msg, + u16 msglen) +{ + if (msglen < virtchnl_struct_size(qs_msg, chunks, 0)) + return false; + + if (msglen < virtchnl_struct_size(qs_msg, chunks, qs_msg->num_chunks)) + return false; + + if (!qs_msg->num_chunks) + return false; + + if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) + return false; + + if (!ice_vc_isvalid_vsi_id(vf, qs_msg->vport_id)) + return false; + + for (int i = 0; i < qs_msg->num_chunks; i++) { + u32 max_queue_in_chunk; + + if (!ice_vc_supported_queue_type(qs_msg->chunks[i].type)) + return false; + + if (!qs_msg->chunks[i].num_queues) + return false; + + max_queue_in_chunk = qs_msg->chunks[i].start_queue_id + + qs_msg->chunks[i].num_queues; + if (max_queue_in_chunk > vf->num_vf_qs) + return false; + } + + return true; +} + +#define ice_for_each_q_in_chunk(chunk, q_id) \ + for ((q_id) = (chunk)->start_queue_id; \ + (q_id) < (chunk)->start_queue_id + (chunk)->num_queues; \ + (q_id)++) + +static int +ice_vc_ena_rxq_chunk(struct ice_vf *vf, struct virtchnl_queue_chunk *chunk) +{ + struct ice_vsi *vsi; + u32 vf_qid; + + ice_for_each_q_in_chunk(chunk, vf_qid) { + int err; + + vsi = ice_get_vf_vsi(vf); + err = ice_vf_vsi_ena_single_rxq(vf, vsi, vf_qid); + if (err) + return err; + } + + return 0; +} + +static int +ice_vc_ena_txq_chunk(struct ice_vf *vf, struct virtchnl_queue_chunk *chunk) +{ + struct ice_vsi *vsi; + u32 vf_qid; + + ice_for_each_q_in_chunk(chunk, vf_qid) { + vsi = ice_get_vf_vsi(vf); + ice_vf_vsi_ena_single_txq(vf, vsi, vf_qid); + } + + return 0; +} + +/** + * ice_vc_ena_qs_v2_msg - message handling for VIRTCHNL_OP_ENABLE_QUEUES_V2 + * @vf: source of the request + * @msg: message to handle + * @msglen: length of the @msg + * + * Return: 0 on success or negative on error. + */ +int ice_vc_ena_qs_v2_msg(struct ice_vf *vf, u8 *msg, u16 msglen) +{ + struct virtchnl_del_ena_dis_queues *ena_qs_msg = + (struct virtchnl_del_ena_dis_queues *)msg; + enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM; + + if (!ice_vc_validate_qs_v2_msg(vf, ena_qs_msg, msglen)) + goto error_param; + + for (int i = 0; i < ena_qs_msg->num_chunks; i++) { + struct virtchnl_queue_chunk *chunk = &ena_qs_msg->chunks[i]; + + if (chunk->type == VIRTCHNL_QUEUE_TYPE_RX && + ice_vc_ena_rxq_chunk(vf, chunk)) + goto error_param; + else if (chunk->type == VIRTCHNL_QUEUE_TYPE_TX && + ice_vc_ena_txq_chunk(vf, chunk)) + goto error_param; + } + + v_ret = VIRTCHNL_STATUS_SUCCESS; + set_bit(ICE_VF_STATE_QS_ENA, vf->vf_states); + +error_param: + return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_QUEUES_V2, + v_ret, NULL, 0); +} + +static int +ice_vc_dis_rxq_chunk(struct ice_vf *vf, struct virtchnl_queue_chunk *chunk) +{ + struct ice_vsi *vsi; + u32 vf_qid; + + ice_for_each_q_in_chunk(chunk, vf_qid) { + int err; + + vsi = ice_get_vf_vsi(vf); + err = ice_vf_vsi_dis_single_rxq(vf, vsi, vf_qid); + if (err) + return err; + } + + return 0; +} + +static int +ice_vc_dis_txq_chunk(struct ice_vf *vf, struct virtchnl_queue_chunk *chunk) +{ + struct ice_vsi *vsi; + u32 vf_qid; + + ice_for_each_q_in_chunk(chunk, vf_qid) { + int err; + + vsi = ice_get_vf_vsi(vf); + err = ice_vf_vsi_dis_single_txq(vf, vsi, vf_qid); + if (err) + return err; + } + + return 0; +} + +/** + * ice_vc_dis_qs_v2_msg - message handling for VIRTCHNL_OP_DISABLE_QUEUES_V2 + * @vf: source of the request + * @msg: message to handle + * @msglen: length of @msg + * + * Return: 0 on success or negative on error. + */ +int ice_vc_dis_qs_v2_msg(struct ice_vf *vf, u8 *msg, u16 msglen) +{ + struct virtchnl_del_ena_dis_queues *dis_qs_msg = + (struct virtchnl_del_ena_dis_queues *)msg; + enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM; + + if (!ice_vc_validate_qs_v2_msg(vf, dis_qs_msg, msglen)) + goto error_param; + + for (int i = 0; i < dis_qs_msg->num_chunks; i++) { + struct virtchnl_queue_chunk *chunk = &dis_qs_msg->chunks[i]; + + if (chunk->type == VIRTCHNL_QUEUE_TYPE_RX && + ice_vc_dis_rxq_chunk(vf, chunk)) + goto error_param; + else if (chunk->type == VIRTCHNL_QUEUE_TYPE_TX && + ice_vc_dis_txq_chunk(vf, chunk)) + goto error_param; + } + + v_ret = VIRTCHNL_STATUS_SUCCESS; + if (ice_vf_has_no_qs_ena(vf)) + clear_bit(ICE_VF_STATE_QS_ENA, vf->vf_states); + +error_param: + return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_QUEUES_V2, + v_ret, NULL, 0); +} + +/** + * ice_vc_validate_qv_maps - validate parameters sent in the qs_msg structure + * @vf: VF the message was received from + * @qv_maps: contents of the message from the VF + * @msglen: length of the @qv_maps + * + * Used to validate VIRTCHNL_OP_MAP_QUEUE_VECTOR messages. This should always + * be called before attempting map interrupts to queues. If all checks succeed, + * then return success indicating to the caller that the qv_maps are valid. + * Otherwise return false, indicating to the caller that the qv_maps are + * invalid. + * + * Return: true if parameters are valid, false otherwise. + */ +static bool ice_vc_validate_qv_maps(struct ice_vf *vf, + struct virtchnl_queue_vector_maps *qv_maps, + u16 msglen) +{ + struct ice_vsi *vsi; + int total_vectors; + + vsi = ice_get_vf_vsi(vf); + if (!vsi) + return false; + + if (msglen < virtchnl_struct_size(qv_maps, qv_maps, 0)) + return false; + + if (msglen < virtchnl_struct_size(qv_maps, qv_maps, qv_maps->num_qv_maps)) + return false; + + if (!qv_maps->num_qv_maps) + return false; + + if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) + return false; + + if (!ice_vc_isvalid_vsi_id(vf, qv_maps->vport_id)) + return false; + + total_vectors = vsi->num_q_vectors + ICE_NONQ_VECS_VF; + + for (int i = 0; i < qv_maps->num_qv_maps; i++) { + if (!ice_vc_supported_queue_type(qv_maps->qv_maps[i].queue_type)) + return false; + + if (qv_maps->qv_maps[i].queue_id >= vf->num_vf_qs) + return false; + + if (qv_maps->qv_maps[i].vector_id >= total_vectors || + qv_maps->qv_maps[i].vector_id < ICE_NONQ_VECS_VF) + return false; + + if (qv_maps->qv_maps[i].itr_idx < ICE_IDX_ITR0 || + qv_maps->qv_maps[i].itr_idx > ICE_ITR_NONE) + return false; + } + + return true; +} + +/** + * ice_vc_map_q_vector_msg - message handling for VIRTCHNL_OP_MAP_QUEUE_VECTOR + * @vf: source of the request + * @msg: message to handle + * @msglen: length of @msg + * + * Return: 0 on success or negative on error + */ +int ice_vc_map_q_vector_msg(struct ice_vf *vf, u8 *msg, u16 msglen) +{ + enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM; + struct virtchnl_queue_vector_maps *qv_maps; + struct ice_vsi *vsi; + + qv_maps = (struct virtchnl_queue_vector_maps *)msg; + + if (!ice_vc_validate_qv_maps(vf, qv_maps, msglen)) + goto error_param; + + for (int i = 0; i < qv_maps->num_qv_maps; i++) { + struct virtchnl_queue_vector *qv_map = &qv_maps->qv_maps[i]; + struct ice_q_vector *q_vector; + u16 vector_id; + int vsi_q_id; + + vsi_q_id = qv_map->queue_id; + vector_id = qv_map->vector_id; + vsi = ice_get_vf_vsi(vf); + if (!vsi) + goto error_param; + + q_vector = vf->vf_ops->get_q_vector(vsi, vector_id); + if (!q_vector) + goto error_param; + + if (!ice_vc_isvalid_q_id(vsi, vsi_q_id)) + goto error_param; + + if (qv_map->queue_type == VIRTCHNL_QUEUE_TYPE_RX) + ice_cfg_rxq_interrupt(vsi, vsi_q_id, + q_vector->vf_reg_idx, + qv_map->itr_idx); + else if (qv_map->queue_type == VIRTCHNL_QUEUE_TYPE_TX) + ice_cfg_txq_interrupt(vsi, vsi_q_id, + q_vector->vf_reg_idx, + qv_map->itr_idx); + } + + v_ret = VIRTCHNL_STATUS_SUCCESS; + +error_param: + return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_MAP_QUEUE_VECTOR, + v_ret, NULL, 0); +} -- 2.51.1