From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) (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 A55C631195B for ; Wed, 27 Aug 2025 22:46:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.12 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756334822; cv=none; b=etvT985/fa8lJMUKr+XtGPV/1sf54kJG/Yf8JTKYd+iduwpfLuJ1nokOCWQ5S6d9A+RZEt22U7JyOz2GtlT8QLkos+1qVhS+G21nV7z307tm7ORccl2whz+a+u5sZjf7ZaaLaC64OsUblz7MmHA1Z84yhhoDMc1dt6Y6eLZ2Bh0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756334822; c=relaxed/simple; bh=PMV5h/Bn8daDPiJJc0YEqrB9eCtsz4AlW2CUYWawVgo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HbTfX0dqseyruOFqw11s49DlXWqa+6ijLEquXMx2l35rii1oBWV3QGdRssDG+EiSOpn4TqRcCYmgfMofUc4GolEAPCTCsrjwnXmh8By/ijTE0aVQ+RQ56tzrVBZ0mHtNB6zgdBwkj5mKfAPYFq2s+4E6CmNuU4KJAfPyYPCTDRY= 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=SZq0oIPb; arc=none smtp.client-ip=198.175.65.12 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="SZq0oIPb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1756334820; x=1787870820; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PMV5h/Bn8daDPiJJc0YEqrB9eCtsz4AlW2CUYWawVgo=; b=SZq0oIPbiTGt55/pOGQJh0lvTc7+SxLwFZv58QaB9RVmGYKq8gOmF+mw iJkg+WzcV65fJBcyiGDJ9ojbGxxelkdhzYDnKDSRTQQqwY2vLn3nwHB+u CWkVIqsT/vAnEc5DYje+20lIMyFLtkF5g0cMIxDy6RZoDXTz5oCasn5un 9Wu0Tc/FZdj2sQLidso8MABIyVw6ilBuqSLWFz5zIqMXkpGeocFfF70O4 C7/Tb/RE1LovSmCS844BjrDUmqLyNxXZvfQ+h7Zc3SBFVo7CSk8wbh54w cvpRI1cs2uXjo9xYMdi1hO9kO+KNOJ5fSOu8aD6A/7vqbor4vaQ37Rz+b g==; X-CSE-ConnectionGUID: 3dkxpWrwQxe9aR058YkmqQ== X-CSE-MsgGUID: BXv7W3NjRG2G0gg8A8jIFQ== X-IronPort-AV: E=McAfee;i="6800,10657,11535"; a="70037287" X-IronPort-AV: E=Sophos;i="6.18,217,1751266800"; d="scan'208";a="70037287" Received: from orviesa009.jf.intel.com ([10.64.159.149]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Aug 2025 15:46:51 -0700 X-CSE-ConnectionGUID: L7AHpetmRfGkBZpATQ2fwg== X-CSE-MsgGUID: wXPdTS87QUmvb5j3YFlmFw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.18,217,1751266800"; d="scan'208";a="169555038" Received: from anguy11-upstream.jf.intel.com ([10.166.9.133]) by orviesa009.jf.intel.com with ESMTP; 27 Aug 2025 15:46:51 -0700 From: Tony Nguyen To: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com, edumazet@google.com, andrew+netdev@lunn.ch, netdev@vger.kernel.org Cc: Przemek Kitszel , anthony.l.nguyen@intel.com, gregkh@linuxfoundation.org, sashal@kernel.org, kuniyu@google.com Subject: [PATCH net-next 11/12] ice: extract virt/rss.c: cleanup - p2 Date: Wed, 27 Aug 2025 15:46:26 -0700 Message-ID: <20250827224641.415806-12-anthony.l.nguyen@intel.com> X-Mailer: git-send-email 2.47.1 In-Reply-To: <20250827224641.415806-1-anthony.l.nguyen@intel.com> References: <20250827224641.415806-1-anthony.l.nguyen@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: Przemek Kitszel Remove remaining portion of the stuff that stays within virtchnl.c, (separate commits to have nicer, removal-only, history). Signed-off-by: Przemek Kitszel Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/virt/rss.c | 1521 --------------------- 1 file changed, 1521 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/virt/rss.c b/drivers/net/ethernet/intel/ice/virt/rss.c index 5003f48e8a84..04bbb2b097a8 100644 --- a/drivers/net/ethernet/intel/ice/virt/rss.c +++ b/drivers/net/ethernet/intel/ice/virt/rss.c @@ -716,1524 +716,3 @@ static int ice_vc_set_rss_hashcfg(struct ice_vf *vf, u8 *msg) NULL, 0); } -/** - * ice_vc_query_rxdid - query RXDID supported by DDP package - * @vf: pointer to VF info - * - * Called from VF to query a bitmap of supported flexible - * descriptor RXDIDs of a DDP package. - */ -static int ice_vc_query_rxdid(struct ice_vf *vf) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct ice_pf *pf = vf->pf; - u64 rxdid; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto err; - } - - if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_RX_FLEX_DESC)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto err; - } - - rxdid = pf->supported_rxdids; - -err: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_SUPPORTED_RXDIDS, - v_ret, (u8 *)&rxdid, sizeof(rxdid)); -} - -/** - * ice_vf_init_vlan_stripping - enable/disable VLAN stripping on initialization - * @vf: VF to enable/disable VLAN stripping for on initialization - * - * Set the default for VLAN stripping based on whether a port VLAN is configured - * and the current VLAN mode of the device. - */ -static int ice_vf_init_vlan_stripping(struct ice_vf *vf) -{ - struct ice_vsi *vsi = ice_get_vf_vsi(vf); - - vf->vlan_strip_ena = 0; - - if (!vsi) - return -EINVAL; - - /* don't modify stripping if port VLAN is configured in SVM since the - * port VLAN is based on the inner/single VLAN in SVM - */ - if (ice_vf_is_port_vlan_ena(vf) && !ice_is_dvm_ena(&vsi->back->hw)) - return 0; - - if (ice_vf_vlan_offload_ena(vf->driver_caps)) { - int err; - - err = vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q); - if (!err) - vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA; - return err; - } - - return vsi->inner_vlan_ops.dis_stripping(vsi); -} - -static u16 ice_vc_get_max_vlan_fltrs(struct ice_vf *vf) -{ - if (vf->trusted) - return VLAN_N_VID; - else - return ICE_MAX_VLAN_PER_VF; -} - -/** - * ice_vf_outer_vlan_not_allowed - check if outer VLAN can be used - * @vf: VF that being checked for - * - * When the device is in double VLAN mode, check whether or not the outer VLAN - * is allowed. - */ -static bool ice_vf_outer_vlan_not_allowed(struct ice_vf *vf) -{ - if (ice_vf_is_port_vlan_ena(vf)) - return true; - - return false; -} - -/** - * ice_vc_set_dvm_caps - set VLAN capabilities when the device is in DVM - * @vf: VF that capabilities are being set for - * @caps: VLAN capabilities to populate - * - * Determine VLAN capabilities support based on whether a port VLAN is - * configured. If a port VLAN is configured then the VF should use the inner - * filtering/offload capabilities since the port VLAN is using the outer VLAN - * capabilies. - */ -static void -ice_vc_set_dvm_caps(struct ice_vf *vf, struct virtchnl_vlan_caps *caps) -{ - struct virtchnl_vlan_supported_caps *supported_caps; - - if (ice_vf_outer_vlan_not_allowed(vf)) { - /* until support for inner VLAN filtering is added when a port - * VLAN is configured, only support software offloaded inner - * VLANs when a port VLAN is confgured in DVM - */ - supported_caps = &caps->filtering.filtering_support; - supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED; - - supported_caps = &caps->offloads.stripping_support; - supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - supported_caps = &caps->offloads.insertion_support; - supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100; - caps->offloads.ethertype_match = - VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION; - } else { - supported_caps = &caps->filtering.filtering_support; - supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED; - supported_caps->outer = VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_ETHERTYPE_88A8 | - VIRTCHNL_VLAN_ETHERTYPE_9100 | - VIRTCHNL_VLAN_ETHERTYPE_AND; - caps->filtering.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_ETHERTYPE_88A8 | - VIRTCHNL_VLAN_ETHERTYPE_9100; - - supported_caps = &caps->offloads.stripping_support; - supported_caps->inner = VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1; - supported_caps->outer = VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_ETHERTYPE_88A8 | - VIRTCHNL_VLAN_ETHERTYPE_9100 | - VIRTCHNL_VLAN_ETHERTYPE_XOR | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2; - - supported_caps = &caps->offloads.insertion_support; - supported_caps->inner = VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1; - supported_caps->outer = VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_ETHERTYPE_88A8 | - VIRTCHNL_VLAN_ETHERTYPE_9100 | - VIRTCHNL_VLAN_ETHERTYPE_XOR | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2; - - caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100; - - caps->offloads.ethertype_match = - VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION; - } - - caps->filtering.max_filters = ice_vc_get_max_vlan_fltrs(vf); -} - -/** - * ice_vc_set_svm_caps - set VLAN capabilities when the device is in SVM - * @vf: VF that capabilities are being set for - * @caps: VLAN capabilities to populate - * - * Determine VLAN capabilities support based on whether a port VLAN is - * configured. If a port VLAN is configured then the VF does not have any VLAN - * filtering or offload capabilities since the port VLAN is using the inner VLAN - * capabilities in single VLAN mode (SVM). Otherwise allow the VF to use inner - * VLAN fitlering and offload capabilities. - */ -static void -ice_vc_set_svm_caps(struct ice_vf *vf, struct virtchnl_vlan_caps *caps) -{ - struct virtchnl_vlan_supported_caps *supported_caps; - - if (ice_vf_is_port_vlan_ena(vf)) { - supported_caps = &caps->filtering.filtering_support; - supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - supported_caps = &caps->offloads.stripping_support; - supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - supported_caps = &caps->offloads.insertion_support; - supported_caps->inner = VIRTCHNL_VLAN_UNSUPPORTED; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - caps->offloads.ethertype_init = VIRTCHNL_VLAN_UNSUPPORTED; - caps->offloads.ethertype_match = VIRTCHNL_VLAN_UNSUPPORTED; - caps->filtering.max_filters = 0; - } else { - supported_caps = &caps->filtering.filtering_support; - supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - caps->filtering.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100; - - supported_caps = &caps->offloads.stripping_support; - supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - supported_caps = &caps->offloads.insertion_support; - supported_caps->inner = VIRTCHNL_VLAN_ETHERTYPE_8100 | - VIRTCHNL_VLAN_TOGGLE | - VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1; - supported_caps->outer = VIRTCHNL_VLAN_UNSUPPORTED; - - caps->offloads.ethertype_init = VIRTCHNL_VLAN_ETHERTYPE_8100; - caps->offloads.ethertype_match = - VIRTCHNL_ETHERTYPE_STRIPPING_MATCHES_INSERTION; - caps->filtering.max_filters = ice_vc_get_max_vlan_fltrs(vf); - } -} - -/** - * ice_vc_get_offload_vlan_v2_caps - determine VF's VLAN capabilities - * @vf: VF to determine VLAN capabilities for - * - * This will only be called if the VF and PF successfully negotiated - * VIRTCHNL_VF_OFFLOAD_VLAN_V2. - * - * Set VLAN capabilities based on the current VLAN mode and whether a port VLAN - * is configured or not. - */ -static int ice_vc_get_offload_vlan_v2_caps(struct ice_vf *vf) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_vlan_caps *caps = NULL; - int err, len = 0; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - caps = kzalloc(sizeof(*caps), GFP_KERNEL); - if (!caps) { - v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; - goto out; - } - len = sizeof(*caps); - - if (ice_is_dvm_ena(&vf->pf->hw)) - ice_vc_set_dvm_caps(vf, caps); - else - ice_vc_set_svm_caps(vf, caps); - - /* store negotiated caps to prevent invalid VF messages */ - memcpy(&vf->vlan_v2_caps, caps, sizeof(*caps)); - -out: - err = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS, - v_ret, (u8 *)caps, len); - kfree(caps); - return err; -} - -/** - * ice_vc_validate_vlan_tpid - validate VLAN TPID - * @filtering_caps: negotiated/supported VLAN filtering capabilities - * @tpid: VLAN TPID used for validation - * - * Convert the VLAN TPID to a VIRTCHNL_VLAN_ETHERTYPE_* and then compare against - * the negotiated/supported filtering caps to see if the VLAN TPID is valid. - */ -static bool ice_vc_validate_vlan_tpid(u16 filtering_caps, u16 tpid) -{ - enum virtchnl_vlan_support vlan_ethertype = VIRTCHNL_VLAN_UNSUPPORTED; - - switch (tpid) { - case ETH_P_8021Q: - vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_8100; - break; - case ETH_P_8021AD: - vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_88A8; - break; - case ETH_P_QINQ1: - vlan_ethertype = VIRTCHNL_VLAN_ETHERTYPE_9100; - break; - } - - if (!(filtering_caps & vlan_ethertype)) - return false; - - return true; -} - -/** - * ice_vc_is_valid_vlan - validate the virtchnl_vlan - * @vc_vlan: virtchnl_vlan to validate - * - * If the VLAN TCI and VLAN TPID are 0, then this filter is invalid, so return - * false. Otherwise return true. - */ -static bool ice_vc_is_valid_vlan(struct virtchnl_vlan *vc_vlan) -{ - if (!vc_vlan->tci || !vc_vlan->tpid) - return false; - - return true; -} - -/** - * ice_vc_validate_vlan_filter_list - validate the filter list from the VF - * @vfc: negotiated/supported VLAN filtering capabilities - * @vfl: VLAN filter list from VF to validate - * - * Validate all of the filters in the VLAN filter list from the VF. If any of - * the checks fail then return false. Otherwise return true. - */ -static bool -ice_vc_validate_vlan_filter_list(struct virtchnl_vlan_filtering_caps *vfc, - struct virtchnl_vlan_filter_list_v2 *vfl) -{ - u16 i; - - if (!vfl->num_elements) - return false; - - for (i = 0; i < vfl->num_elements; i++) { - struct virtchnl_vlan_supported_caps *filtering_support = - &vfc->filtering_support; - struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i]; - struct virtchnl_vlan *outer = &vlan_fltr->outer; - struct virtchnl_vlan *inner = &vlan_fltr->inner; - - if ((ice_vc_is_valid_vlan(outer) && - filtering_support->outer == VIRTCHNL_VLAN_UNSUPPORTED) || - (ice_vc_is_valid_vlan(inner) && - filtering_support->inner == VIRTCHNL_VLAN_UNSUPPORTED)) - return false; - - if ((outer->tci_mask && - !(filtering_support->outer & VIRTCHNL_VLAN_FILTER_MASK)) || - (inner->tci_mask && - !(filtering_support->inner & VIRTCHNL_VLAN_FILTER_MASK))) - return false; - - if (((outer->tci & VLAN_PRIO_MASK) && - !(filtering_support->outer & VIRTCHNL_VLAN_PRIO)) || - ((inner->tci & VLAN_PRIO_MASK) && - !(filtering_support->inner & VIRTCHNL_VLAN_PRIO))) - return false; - - if ((ice_vc_is_valid_vlan(outer) && - !ice_vc_validate_vlan_tpid(filtering_support->outer, - outer->tpid)) || - (ice_vc_is_valid_vlan(inner) && - !ice_vc_validate_vlan_tpid(filtering_support->inner, - inner->tpid))) - return false; - } - - return true; -} - -/** - * ice_vc_to_vlan - transform from struct virtchnl_vlan to struct ice_vlan - * @vc_vlan: struct virtchnl_vlan to transform - */ -static struct ice_vlan ice_vc_to_vlan(struct virtchnl_vlan *vc_vlan) -{ - struct ice_vlan vlan = { 0 }; - - vlan.prio = FIELD_GET(VLAN_PRIO_MASK, vc_vlan->tci); - vlan.vid = vc_vlan->tci & VLAN_VID_MASK; - vlan.tpid = vc_vlan->tpid; - - return vlan; -} - -/** - * ice_vc_vlan_action - action to perform on the virthcnl_vlan - * @vsi: VF's VSI used to perform the action - * @vlan_action: function to perform the action with (i.e. add/del) - * @vlan: VLAN filter to perform the action with - */ -static int -ice_vc_vlan_action(struct ice_vsi *vsi, - int (*vlan_action)(struct ice_vsi *, struct ice_vlan *), - struct ice_vlan *vlan) -{ - int err; - - err = vlan_action(vsi, vlan); - if (err) - return err; - - return 0; -} - -/** - * ice_vc_del_vlans - delete VLAN(s) from the virtchnl filter list - * @vf: VF used to delete the VLAN(s) - * @vsi: VF's VSI used to delete the VLAN(s) - * @vfl: virthchnl filter list used to delete the filters - */ -static int -ice_vc_del_vlans(struct ice_vf *vf, struct ice_vsi *vsi, - struct virtchnl_vlan_filter_list_v2 *vfl) -{ - bool vlan_promisc = ice_is_vlan_promisc_allowed(vf); - int err; - u16 i; - - for (i = 0; i < vfl->num_elements; i++) { - struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i]; - struct virtchnl_vlan *vc_vlan; - - vc_vlan = &vlan_fltr->outer; - if (ice_vc_is_valid_vlan(vc_vlan)) { - struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan); - - err = ice_vc_vlan_action(vsi, - vsi->outer_vlan_ops.del_vlan, - &vlan); - if (err) - return err; - - if (vlan_promisc) - ice_vf_dis_vlan_promisc(vsi, &vlan); - - /* Disable VLAN filtering when only VLAN 0 is left */ - if (!ice_vsi_has_non_zero_vlans(vsi) && ice_is_dvm_ena(&vsi->back->hw)) { - err = vsi->outer_vlan_ops.dis_tx_filtering(vsi); - if (err) - return err; - } - } - - vc_vlan = &vlan_fltr->inner; - if (ice_vc_is_valid_vlan(vc_vlan)) { - struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan); - - err = ice_vc_vlan_action(vsi, - vsi->inner_vlan_ops.del_vlan, - &vlan); - if (err) - return err; - - /* no support for VLAN promiscuous on inner VLAN unless - * we are in Single VLAN Mode (SVM) - */ - if (!ice_is_dvm_ena(&vsi->back->hw)) { - if (vlan_promisc) - ice_vf_dis_vlan_promisc(vsi, &vlan); - - /* Disable VLAN filtering when only VLAN 0 is left */ - if (!ice_vsi_has_non_zero_vlans(vsi)) { - err = vsi->inner_vlan_ops.dis_tx_filtering(vsi); - if (err) - return err; - } - } - } - } - - return 0; -} - -/** - * ice_vc_remove_vlan_v2_msg - virtchnl handler for VIRTCHNL_OP_DEL_VLAN_V2 - * @vf: VF the message was received from - * @msg: message received from the VF - */ -static int ice_vc_remove_vlan_v2_msg(struct ice_vf *vf, u8 *msg) -{ - struct virtchnl_vlan_filter_list_v2 *vfl = - (struct virtchnl_vlan_filter_list_v2 *)msg; - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct ice_vsi *vsi; - - if (!ice_vc_validate_vlan_filter_list(&vf->vlan_v2_caps.filtering, - vfl)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_isvalid_vsi_id(vf, vfl->vport_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (ice_vc_del_vlans(vf, vsi, vfl)) - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - -out: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_VLAN_V2, v_ret, NULL, - 0); -} - -/** - * ice_vc_add_vlans - add VLAN(s) from the virtchnl filter list - * @vf: VF used to add the VLAN(s) - * @vsi: VF's VSI used to add the VLAN(s) - * @vfl: virthchnl filter list used to add the filters - */ -static int -ice_vc_add_vlans(struct ice_vf *vf, struct ice_vsi *vsi, - struct virtchnl_vlan_filter_list_v2 *vfl) -{ - bool vlan_promisc = ice_is_vlan_promisc_allowed(vf); - int err; - u16 i; - - for (i = 0; i < vfl->num_elements; i++) { - struct virtchnl_vlan_filter *vlan_fltr = &vfl->filters[i]; - struct virtchnl_vlan *vc_vlan; - - vc_vlan = &vlan_fltr->outer; - if (ice_vc_is_valid_vlan(vc_vlan)) { - struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan); - - err = ice_vc_vlan_action(vsi, - vsi->outer_vlan_ops.add_vlan, - &vlan); - if (err) - return err; - - if (vlan_promisc) { - err = ice_vf_ena_vlan_promisc(vf, vsi, &vlan); - if (err) - return err; - } - - /* Enable VLAN filtering on first non-zero VLAN */ - if (vf->spoofchk && vlan.vid && ice_is_dvm_ena(&vsi->back->hw)) { - err = vsi->outer_vlan_ops.ena_tx_filtering(vsi); - if (err) - return err; - } - } - - vc_vlan = &vlan_fltr->inner; - if (ice_vc_is_valid_vlan(vc_vlan)) { - struct ice_vlan vlan = ice_vc_to_vlan(vc_vlan); - - err = ice_vc_vlan_action(vsi, - vsi->inner_vlan_ops.add_vlan, - &vlan); - if (err) - return err; - - /* no support for VLAN promiscuous on inner VLAN unless - * we are in Single VLAN Mode (SVM) - */ - if (!ice_is_dvm_ena(&vsi->back->hw)) { - if (vlan_promisc) { - err = ice_vf_ena_vlan_promisc(vf, vsi, - &vlan); - if (err) - return err; - } - - /* Enable VLAN filtering on first non-zero VLAN */ - if (vf->spoofchk && vlan.vid) { - err = vsi->inner_vlan_ops.ena_tx_filtering(vsi); - if (err) - return err; - } - } - } - } - - return 0; -} - -/** - * ice_vc_validate_add_vlan_filter_list - validate add filter list from the VF - * @vsi: VF VSI used to get number of existing VLAN filters - * @vfc: negotiated/supported VLAN filtering capabilities - * @vfl: VLAN filter list from VF to validate - * - * Validate all of the filters in the VLAN filter list from the VF during the - * VIRTCHNL_OP_ADD_VLAN_V2 opcode. If any of the checks fail then return false. - * Otherwise return true. - */ -static bool -ice_vc_validate_add_vlan_filter_list(struct ice_vsi *vsi, - struct virtchnl_vlan_filtering_caps *vfc, - struct virtchnl_vlan_filter_list_v2 *vfl) -{ - u16 num_requested_filters = ice_vsi_num_non_zero_vlans(vsi) + - vfl->num_elements; - - if (num_requested_filters > vfc->max_filters) - return false; - - return ice_vc_validate_vlan_filter_list(vfc, vfl); -} - -/** - * ice_vc_add_vlan_v2_msg - virtchnl handler for VIRTCHNL_OP_ADD_VLAN_V2 - * @vf: VF the message was received from - * @msg: message received from the VF - */ -static int ice_vc_add_vlan_v2_msg(struct ice_vf *vf, u8 *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_vlan_filter_list_v2 *vfl = - (struct virtchnl_vlan_filter_list_v2 *)msg; - struct ice_vsi *vsi; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_isvalid_vsi_id(vf, vfl->vport_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_validate_add_vlan_filter_list(vsi, - &vf->vlan_v2_caps.filtering, - vfl)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (ice_vc_add_vlans(vf, vsi, vfl)) - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - -out: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_VLAN_V2, v_ret, NULL, - 0); -} - -/** - * ice_vc_valid_vlan_setting - validate VLAN setting - * @negotiated_settings: negotiated VLAN settings during VF init - * @ethertype_setting: ethertype(s) requested for the VLAN setting - */ -static bool -ice_vc_valid_vlan_setting(u32 negotiated_settings, u32 ethertype_setting) -{ - if (ethertype_setting && !(negotiated_settings & ethertype_setting)) - return false; - - /* only allow a single VIRTCHNL_VLAN_ETHERTYPE if - * VIRTHCNL_VLAN_ETHERTYPE_AND is not negotiated/supported - */ - if (!(negotiated_settings & VIRTCHNL_VLAN_ETHERTYPE_AND) && - hweight32(ethertype_setting) > 1) - return false; - - /* ability to modify the VLAN setting was not negotiated */ - if (!(negotiated_settings & VIRTCHNL_VLAN_TOGGLE)) - return false; - - return true; -} - -/** - * ice_vc_valid_vlan_setting_msg - validate the VLAN setting message - * @caps: negotiated VLAN settings during VF init - * @msg: message to validate - * - * Used to validate any VLAN virtchnl message sent as a - * virtchnl_vlan_setting structure. Validates the message against the - * negotiated/supported caps during VF driver init. - */ -static bool -ice_vc_valid_vlan_setting_msg(struct virtchnl_vlan_supported_caps *caps, - struct virtchnl_vlan_setting *msg) -{ - if ((!msg->outer_ethertype_setting && - !msg->inner_ethertype_setting) || - (!caps->outer && !caps->inner)) - return false; - - if (msg->outer_ethertype_setting && - !ice_vc_valid_vlan_setting(caps->outer, - msg->outer_ethertype_setting)) - return false; - - if (msg->inner_ethertype_setting && - !ice_vc_valid_vlan_setting(caps->inner, - msg->inner_ethertype_setting)) - return false; - - return true; -} - -/** - * ice_vc_get_tpid - transform from VIRTCHNL_VLAN_ETHERTYPE_* to VLAN TPID - * @ethertype_setting: VIRTCHNL_VLAN_ETHERTYPE_* used to get VLAN TPID - * @tpid: VLAN TPID to populate - */ -static int ice_vc_get_tpid(u32 ethertype_setting, u16 *tpid) -{ - switch (ethertype_setting) { - case VIRTCHNL_VLAN_ETHERTYPE_8100: - *tpid = ETH_P_8021Q; - break; - case VIRTCHNL_VLAN_ETHERTYPE_88A8: - *tpid = ETH_P_8021AD; - break; - case VIRTCHNL_VLAN_ETHERTYPE_9100: - *tpid = ETH_P_QINQ1; - break; - default: - *tpid = 0; - return -EINVAL; - } - - return 0; -} - -/** - * ice_vc_ena_vlan_offload - enable VLAN offload based on the ethertype_setting - * @vsi: VF's VSI used to enable the VLAN offload - * @ena_offload: function used to enable the VLAN offload - * @ethertype_setting: VIRTCHNL_VLAN_ETHERTYPE_* to enable offloads for - */ -static int -ice_vc_ena_vlan_offload(struct ice_vsi *vsi, - int (*ena_offload)(struct ice_vsi *vsi, u16 tpid), - u32 ethertype_setting) -{ - u16 tpid; - int err; - - err = ice_vc_get_tpid(ethertype_setting, &tpid); - if (err) - return err; - - err = ena_offload(vsi, tpid); - if (err) - return err; - - return 0; -} - -/** - * ice_vc_ena_vlan_stripping_v2_msg - * @vf: VF the message was received from - * @msg: message received from the VF - * - * virthcnl handler for VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2 - */ -static int ice_vc_ena_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_vlan_supported_caps *stripping_support; - struct virtchnl_vlan_setting *strip_msg = - (struct virtchnl_vlan_setting *)msg; - u32 ethertype_setting; - struct ice_vsi *vsi; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_isvalid_vsi_id(vf, strip_msg->vport_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - stripping_support = &vf->vlan_v2_caps.offloads.stripping_support; - if (!ice_vc_valid_vlan_setting_msg(stripping_support, strip_msg)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (ice_vsi_is_rxq_crc_strip_dis(vsi)) { - v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED; - goto out; - } - - ethertype_setting = strip_msg->outer_ethertype_setting; - if (ethertype_setting) { - if (ice_vc_ena_vlan_offload(vsi, - vsi->outer_vlan_ops.ena_stripping, - ethertype_setting)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } else { - enum ice_l2tsel l2tsel = - ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG2_2ND; - - /* PF tells the VF that the outer VLAN tag is always - * extracted to VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 and - * inner is always extracted to - * VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1. This is needed to - * support outer stripping so the first tag always ends - * up in L2TAG2_2ND and the second/inner tag, if - * enabled, is extracted in L2TAG1. - */ - ice_vsi_update_l2tsel(vsi, l2tsel); - - vf->vlan_strip_ena |= ICE_OUTER_VLAN_STRIP_ENA; - } - } - - ethertype_setting = strip_msg->inner_ethertype_setting; - if (ethertype_setting && - ice_vc_ena_vlan_offload(vsi, vsi->inner_vlan_ops.ena_stripping, - ethertype_setting)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (ethertype_setting) - vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA; - -out: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2, - v_ret, NULL, 0); -} - -/** - * ice_vc_dis_vlan_stripping_v2_msg - * @vf: VF the message was received from - * @msg: message received from the VF - * - * virthcnl handler for VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2 - */ -static int ice_vc_dis_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_vlan_supported_caps *stripping_support; - struct virtchnl_vlan_setting *strip_msg = - (struct virtchnl_vlan_setting *)msg; - u32 ethertype_setting; - struct ice_vsi *vsi; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_isvalid_vsi_id(vf, strip_msg->vport_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - stripping_support = &vf->vlan_v2_caps.offloads.stripping_support; - if (!ice_vc_valid_vlan_setting_msg(stripping_support, strip_msg)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - ethertype_setting = strip_msg->outer_ethertype_setting; - if (ethertype_setting) { - if (vsi->outer_vlan_ops.dis_stripping(vsi)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } else { - enum ice_l2tsel l2tsel = - ICE_L2TSEL_EXTRACT_FIRST_TAG_L2TAG1; - - /* PF tells the VF that the outer VLAN tag is always - * extracted to VIRTCHNL_VLAN_TAG_LOCATION_L2TAG2_2 and - * inner is always extracted to - * VIRTCHNL_VLAN_TAG_LOCATION_L2TAG1. This is needed to - * support inner stripping while outer stripping is - * disabled so that the first and only tag is extracted - * in L2TAG1. - */ - ice_vsi_update_l2tsel(vsi, l2tsel); - - vf->vlan_strip_ena &= ~ICE_OUTER_VLAN_STRIP_ENA; - } - } - - ethertype_setting = strip_msg->inner_ethertype_setting; - if (ethertype_setting && vsi->inner_vlan_ops.dis_stripping(vsi)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (ethertype_setting) - vf->vlan_strip_ena &= ~ICE_INNER_VLAN_STRIP_ENA; - -out: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2, - v_ret, NULL, 0); -} - -/** - * ice_vc_ena_vlan_insertion_v2_msg - * @vf: VF the message was received from - * @msg: message received from the VF - * - * virthcnl handler for VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2 - */ -static int ice_vc_ena_vlan_insertion_v2_msg(struct ice_vf *vf, u8 *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_vlan_supported_caps *insertion_support; - struct virtchnl_vlan_setting *insertion_msg = - (struct virtchnl_vlan_setting *)msg; - u32 ethertype_setting; - struct ice_vsi *vsi; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_isvalid_vsi_id(vf, insertion_msg->vport_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - insertion_support = &vf->vlan_v2_caps.offloads.insertion_support; - if (!ice_vc_valid_vlan_setting_msg(insertion_support, insertion_msg)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - ethertype_setting = insertion_msg->outer_ethertype_setting; - if (ethertype_setting && - ice_vc_ena_vlan_offload(vsi, vsi->outer_vlan_ops.ena_insertion, - ethertype_setting)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - ethertype_setting = insertion_msg->inner_ethertype_setting; - if (ethertype_setting && - ice_vc_ena_vlan_offload(vsi, vsi->inner_vlan_ops.ena_insertion, - ethertype_setting)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - -out: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2, - v_ret, NULL, 0); -} - -/** - * ice_vc_dis_vlan_insertion_v2_msg - * @vf: VF the message was received from - * @msg: message received from the VF - * - * virthcnl handler for VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2 - */ -static int ice_vc_dis_vlan_insertion_v2_msg(struct ice_vf *vf, u8 *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_vlan_supported_caps *insertion_support; - struct virtchnl_vlan_setting *insertion_msg = - (struct virtchnl_vlan_setting *)msg; - u32 ethertype_setting; - struct ice_vsi *vsi; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - if (!ice_vc_isvalid_vsi_id(vf, insertion_msg->vport_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - insertion_support = &vf->vlan_v2_caps.offloads.insertion_support; - if (!ice_vc_valid_vlan_setting_msg(insertion_support, insertion_msg)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - ethertype_setting = insertion_msg->outer_ethertype_setting; - if (ethertype_setting && vsi->outer_vlan_ops.dis_insertion(vsi)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - - ethertype_setting = insertion_msg->inner_ethertype_setting; - if (ethertype_setting && vsi->inner_vlan_ops.dis_insertion(vsi)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto out; - } - -out: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2, - v_ret, NULL, 0); -} - -static int ice_vc_get_ptp_cap(struct ice_vf *vf, - const struct virtchnl_ptp_caps *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM; - u32 caps = VIRTCHNL_1588_PTP_CAP_RX_TSTAMP | - VIRTCHNL_1588_PTP_CAP_READ_PHC; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) - goto err; - - v_ret = VIRTCHNL_STATUS_SUCCESS; - - if (msg->caps & caps) - vf->ptp_caps = caps; - -err: - /* send the response back to the VF */ - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_1588_PTP_GET_CAPS, v_ret, - (u8 *)&vf->ptp_caps, - sizeof(struct virtchnl_ptp_caps)); -} - -static int ice_vc_get_phc_time(struct ice_vf *vf) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_ERR_PARAM; - struct virtchnl_phc_time *phc_time = NULL; - struct ice_pf *pf = vf->pf; - u32 len = 0; - int ret; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states)) - goto err; - - v_ret = VIRTCHNL_STATUS_SUCCESS; - - phc_time = kzalloc(sizeof(*phc_time), GFP_KERNEL); - if (!phc_time) { - v_ret = VIRTCHNL_STATUS_ERR_NO_MEMORY; - goto err; - } - - len = sizeof(*phc_time); - - phc_time->time = ice_ptp_read_src_clk_reg(pf, NULL); - -err: - /* send the response back to the VF */ - ret = ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_1588_PTP_GET_TIME, v_ret, - (u8 *)phc_time, len); - kfree(phc_time); - return ret; -} - -static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = { - .get_ver_msg = ice_vc_get_ver_msg, - .get_vf_res_msg = ice_vc_get_vf_res_msg, - .reset_vf = ice_vc_reset_vf_msg, - .add_mac_addr_msg = ice_vc_add_mac_addr_msg, - .del_mac_addr_msg = ice_vc_del_mac_addr_msg, - .cfg_qs_msg = ice_vc_cfg_qs_msg, - .ena_qs_msg = ice_vc_ena_qs_msg, - .dis_qs_msg = ice_vc_dis_qs_msg, - .request_qs_msg = ice_vc_request_qs_msg, - .cfg_irq_map_msg = ice_vc_cfg_irq_map_msg, - .config_rss_key = ice_vc_config_rss_key, - .config_rss_lut = ice_vc_config_rss_lut, - .config_rss_hfunc = ice_vc_config_rss_hfunc, - .get_stats_msg = ice_vc_get_stats_msg, - .cfg_promiscuous_mode_msg = ice_vc_cfg_promiscuous_mode_msg, - .add_vlan_msg = ice_vc_add_vlan_msg, - .remove_vlan_msg = ice_vc_remove_vlan_msg, - .query_rxdid = ice_vc_query_rxdid, - .get_rss_hashcfg = ice_vc_get_rss_hashcfg, - .set_rss_hashcfg = ice_vc_set_rss_hashcfg, - .ena_vlan_stripping = ice_vc_ena_vlan_stripping, - .dis_vlan_stripping = ice_vc_dis_vlan_stripping, - .handle_rss_cfg_msg = ice_vc_handle_rss_cfg, - .add_fdir_fltr_msg = ice_vc_add_fdir_fltr, - .del_fdir_fltr_msg = ice_vc_del_fdir_fltr, - .get_offload_vlan_v2_caps = ice_vc_get_offload_vlan_v2_caps, - .add_vlan_v2_msg = ice_vc_add_vlan_v2_msg, - .remove_vlan_v2_msg = ice_vc_remove_vlan_v2_msg, - .ena_vlan_stripping_v2_msg = ice_vc_ena_vlan_stripping_v2_msg, - .dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg, - .ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg, - .dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg, - .get_qos_caps = ice_vc_get_qos_caps, - .cfg_q_bw = ice_vc_cfg_q_bw, - .cfg_q_quanta = ice_vc_cfg_q_quanta, - .get_ptp_cap = ice_vc_get_ptp_cap, - .get_phc_time = ice_vc_get_phc_time, - /* If you add a new op here please make sure to add it to - * ice_virtchnl_repr_ops as well. - */ -}; - -/** - * ice_virtchnl_set_dflt_ops - Switch to default virtchnl ops - * @vf: the VF to switch ops - */ -void ice_virtchnl_set_dflt_ops(struct ice_vf *vf) -{ - vf->virtchnl_ops = &ice_virtchnl_dflt_ops; -} - -/** - * ice_vc_repr_add_mac - * @vf: pointer to VF - * @msg: virtchannel message - * - * When port representors are created, we do not add MAC rule - * to firmware, we store it so that PF could report same - * MAC as VF. - */ -static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg) -{ - enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS; - struct virtchnl_ether_addr_list *al = - (struct virtchnl_ether_addr_list *)msg; - struct ice_vsi *vsi; - struct ice_pf *pf; - int i; - - if (!test_bit(ICE_VF_STATE_ACTIVE, vf->vf_states) || - !ice_vc_isvalid_vsi_id(vf, al->vsi_id)) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto handle_mac_exit; - } - - pf = vf->pf; - - vsi = ice_get_vf_vsi(vf); - if (!vsi) { - v_ret = VIRTCHNL_STATUS_ERR_PARAM; - goto handle_mac_exit; - } - - for (i = 0; i < al->num_elements; i++) { - u8 *mac_addr = al->list[i].addr; - - if (!is_unicast_ether_addr(mac_addr) || - ether_addr_equal(mac_addr, vf->hw_lan_addr)) - continue; - - if (vf->pf_set_mac) { - dev_err(ice_pf_to_dev(pf), "VF attempting to override administratively set MAC address\n"); - v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED; - goto handle_mac_exit; - } - - ice_vfhw_mac_add(vf, &al->list[i]); - break; - } - -handle_mac_exit: - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ADD_ETH_ADDR, - v_ret, NULL, 0); -} - -/** - * ice_vc_repr_del_mac - response with success for deleting MAC - * @vf: pointer to VF - * @msg: virtchannel message - * - * Respond with success to not break normal VF flow. - * For legacy VF driver try to update cached MAC address. - */ -static int -ice_vc_repr_del_mac(struct ice_vf __always_unused *vf, u8 __always_unused *msg) -{ - struct virtchnl_ether_addr_list *al = - (struct virtchnl_ether_addr_list *)msg; - - ice_update_legacy_cached_mac(vf, &al->list[0]); - - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DEL_ETH_ADDR, - VIRTCHNL_STATUS_SUCCESS, NULL, 0); -} - -static int -ice_vc_repr_cfg_promiscuous_mode(struct ice_vf *vf, u8 __always_unused *msg) -{ - dev_dbg(ice_pf_to_dev(vf->pf), - "Can't config promiscuous mode in switchdev mode for VF %d\n", - vf->vf_id); - return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE, - VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, - NULL, 0); -} - -static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = { - .get_ver_msg = ice_vc_get_ver_msg, - .get_vf_res_msg = ice_vc_get_vf_res_msg, - .reset_vf = ice_vc_reset_vf_msg, - .add_mac_addr_msg = ice_vc_repr_add_mac, - .del_mac_addr_msg = ice_vc_repr_del_mac, - .cfg_qs_msg = ice_vc_cfg_qs_msg, - .ena_qs_msg = ice_vc_ena_qs_msg, - .dis_qs_msg = ice_vc_dis_qs_msg, - .request_qs_msg = ice_vc_request_qs_msg, - .cfg_irq_map_msg = ice_vc_cfg_irq_map_msg, - .config_rss_key = ice_vc_config_rss_key, - .config_rss_lut = ice_vc_config_rss_lut, - .config_rss_hfunc = ice_vc_config_rss_hfunc, - .get_stats_msg = ice_vc_get_stats_msg, - .cfg_promiscuous_mode_msg = ice_vc_repr_cfg_promiscuous_mode, - .add_vlan_msg = ice_vc_add_vlan_msg, - .remove_vlan_msg = ice_vc_remove_vlan_msg, - .query_rxdid = ice_vc_query_rxdid, - .get_rss_hashcfg = ice_vc_get_rss_hashcfg, - .set_rss_hashcfg = ice_vc_set_rss_hashcfg, - .ena_vlan_stripping = ice_vc_ena_vlan_stripping, - .dis_vlan_stripping = ice_vc_dis_vlan_stripping, - .handle_rss_cfg_msg = ice_vc_handle_rss_cfg, - .add_fdir_fltr_msg = ice_vc_add_fdir_fltr, - .del_fdir_fltr_msg = ice_vc_del_fdir_fltr, - .get_offload_vlan_v2_caps = ice_vc_get_offload_vlan_v2_caps, - .add_vlan_v2_msg = ice_vc_add_vlan_v2_msg, - .remove_vlan_v2_msg = ice_vc_remove_vlan_v2_msg, - .ena_vlan_stripping_v2_msg = ice_vc_ena_vlan_stripping_v2_msg, - .dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg, - .ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg, - .dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg, - .get_qos_caps = ice_vc_get_qos_caps, - .cfg_q_bw = ice_vc_cfg_q_bw, - .cfg_q_quanta = ice_vc_cfg_q_quanta, - .get_ptp_cap = ice_vc_get_ptp_cap, - .get_phc_time = ice_vc_get_phc_time, -}; - -/** - * ice_virtchnl_set_repr_ops - Switch to representor virtchnl ops - * @vf: the VF to switch ops - */ -void ice_virtchnl_set_repr_ops(struct ice_vf *vf) -{ - vf->virtchnl_ops = &ice_virtchnl_repr_ops; -} - -/** - * ice_is_malicious_vf - check if this vf might be overflowing mailbox - * @vf: the VF to check - * @mbxdata: data about the state of the mailbox - * - * Detect if a given VF might be malicious and attempting to overflow the PF - * mailbox. If so, log a warning message and ignore this event. - */ -static bool -ice_is_malicious_vf(struct ice_vf *vf, struct ice_mbx_data *mbxdata) -{ - bool report_malvf = false; - struct device *dev; - struct ice_pf *pf; - int status; - - pf = vf->pf; - dev = ice_pf_to_dev(pf); - - if (test_bit(ICE_VF_STATE_DIS, vf->vf_states)) - return vf->mbx_info.malicious; - - /* check to see if we have a newly malicious VF */ - status = ice_mbx_vf_state_handler(&pf->hw, mbxdata, &vf->mbx_info, - &report_malvf); - if (status) - dev_warn_ratelimited(dev, "Unable to check status of mailbox overflow for VF %u MAC %pM, status %d\n", - vf->vf_id, vf->dev_lan_addr, status); - - if (report_malvf) { - struct ice_vsi *pf_vsi = ice_get_main_vsi(pf); - u8 zero_addr[ETH_ALEN] = {}; - - dev_warn(dev, "VF MAC %pM on PF MAC %pM is generating asynchronous messages and may be overflowing the PF message queue. Please see the Adapter User Guide for more information\n", - vf->dev_lan_addr, - pf_vsi ? pf_vsi->netdev->dev_addr : zero_addr); - } - - return vf->mbx_info.malicious; -} - -/** - * ice_vc_process_vf_msg - Process request from VF - * @pf: pointer to the PF structure - * @event: pointer to the AQ event - * @mbxdata: information used to detect VF attempting mailbox overflow - * - * Called from the common asq/arq handler to process request from VF. When this - * flow is used for devices with hardware VF to PF message queue overflow - * support (ICE_F_MBX_LIMIT) mbxdata is set to NULL and ice_is_malicious_vf - * check is skipped. - */ -void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event, - struct ice_mbx_data *mbxdata) -{ - u32 v_opcode = le32_to_cpu(event->desc.cookie_high); - s16 vf_id = le16_to_cpu(event->desc.retval); - const struct ice_virtchnl_ops *ops; - u16 msglen = event->msg_len; - u8 *msg = event->msg_buf; - struct ice_vf *vf = NULL; - struct device *dev; - int err = 0; - - dev = ice_pf_to_dev(pf); - - vf = ice_get_vf_by_id(pf, vf_id); - if (!vf) { - dev_err(dev, "Unable to locate VF for message from VF ID %d, opcode %d, len %d\n", - vf_id, v_opcode, msglen); - return; - } - - mutex_lock(&vf->cfg_lock); - - /* Check if the VF is trying to overflow the mailbox */ - if (mbxdata && ice_is_malicious_vf(vf, mbxdata)) - goto finish; - - /* Check if VF is disabled. */ - if (test_bit(ICE_VF_STATE_DIS, vf->vf_states)) { - err = -EPERM; - goto error_handler; - } - - ops = vf->virtchnl_ops; - - /* Perform basic checks on the msg */ - err = virtchnl_vc_validate_vf_msg(&vf->vf_ver, v_opcode, msg, msglen); - if (err) { - if (err == VIRTCHNL_STATUS_ERR_PARAM) - err = -EPERM; - else - err = -EINVAL; - } - -error_handler: - if (err) { - ice_vc_send_msg_to_vf(vf, v_opcode, VIRTCHNL_STATUS_ERR_PARAM, - NULL, 0); - dev_err(dev, "Invalid message from VF %d, opcode %d, len %d, error %d\n", - vf_id, v_opcode, msglen, err); - goto finish; - } - - if (!ice_vc_is_opcode_allowed(vf, v_opcode)) { - ice_vc_send_msg_to_vf(vf, v_opcode, - VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, NULL, - 0); - goto finish; - } - - switch (v_opcode) { - case VIRTCHNL_OP_VERSION: - err = ops->get_ver_msg(vf, msg); - break; - case VIRTCHNL_OP_GET_VF_RESOURCES: - err = ops->get_vf_res_msg(vf, msg); - if (ice_vf_init_vlan_stripping(vf)) - dev_dbg(dev, "Failed to initialize VLAN stripping for VF %d\n", - vf->vf_id); - ice_vc_notify_vf_link_state(vf); - break; - case VIRTCHNL_OP_RESET_VF: - ops->reset_vf(vf); - break; - case VIRTCHNL_OP_ADD_ETH_ADDR: - err = ops->add_mac_addr_msg(vf, msg); - break; - case VIRTCHNL_OP_DEL_ETH_ADDR: - err = ops->del_mac_addr_msg(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_VSI_QUEUES: - err = ops->cfg_qs_msg(vf, msg); - break; - case VIRTCHNL_OP_ENABLE_QUEUES: - err = ops->ena_qs_msg(vf, msg); - ice_vc_notify_vf_link_state(vf); - break; - case VIRTCHNL_OP_DISABLE_QUEUES: - err = ops->dis_qs_msg(vf, msg); - break; - case VIRTCHNL_OP_REQUEST_QUEUES: - err = ops->request_qs_msg(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_IRQ_MAP: - err = ops->cfg_irq_map_msg(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_RSS_KEY: - err = ops->config_rss_key(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_RSS_LUT: - err = ops->config_rss_lut(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_RSS_HFUNC: - err = ops->config_rss_hfunc(vf, msg); - break; - case VIRTCHNL_OP_GET_STATS: - err = ops->get_stats_msg(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE: - err = ops->cfg_promiscuous_mode_msg(vf, msg); - break; - case VIRTCHNL_OP_ADD_VLAN: - err = ops->add_vlan_msg(vf, msg); - break; - case VIRTCHNL_OP_DEL_VLAN: - err = ops->remove_vlan_msg(vf, msg); - break; - case VIRTCHNL_OP_GET_SUPPORTED_RXDIDS: - err = ops->query_rxdid(vf); - break; - case VIRTCHNL_OP_GET_RSS_HASHCFG_CAPS: - err = ops->get_rss_hashcfg(vf); - break; - case VIRTCHNL_OP_SET_RSS_HASHCFG: - err = ops->set_rss_hashcfg(vf, msg); - break; - case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING: - err = ops->ena_vlan_stripping(vf); - break; - case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING: - err = ops->dis_vlan_stripping(vf); - break; - case VIRTCHNL_OP_ADD_FDIR_FILTER: - err = ops->add_fdir_fltr_msg(vf, msg); - break; - case VIRTCHNL_OP_DEL_FDIR_FILTER: - err = ops->del_fdir_fltr_msg(vf, msg); - break; - case VIRTCHNL_OP_ADD_RSS_CFG: - err = ops->handle_rss_cfg_msg(vf, msg, true); - break; - case VIRTCHNL_OP_DEL_RSS_CFG: - err = ops->handle_rss_cfg_msg(vf, msg, false); - break; - case VIRTCHNL_OP_GET_OFFLOAD_VLAN_V2_CAPS: - err = ops->get_offload_vlan_v2_caps(vf); - break; - case VIRTCHNL_OP_ADD_VLAN_V2: - err = ops->add_vlan_v2_msg(vf, msg); - break; - case VIRTCHNL_OP_DEL_VLAN_V2: - err = ops->remove_vlan_v2_msg(vf, msg); - break; - case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2: - err = ops->ena_vlan_stripping_v2_msg(vf, msg); - break; - case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2: - err = ops->dis_vlan_stripping_v2_msg(vf, msg); - break; - case VIRTCHNL_OP_ENABLE_VLAN_INSERTION_V2: - err = ops->ena_vlan_insertion_v2_msg(vf, msg); - break; - case VIRTCHNL_OP_DISABLE_VLAN_INSERTION_V2: - err = ops->dis_vlan_insertion_v2_msg(vf, msg); - break; - case VIRTCHNL_OP_GET_QOS_CAPS: - err = ops->get_qos_caps(vf); - break; - case VIRTCHNL_OP_CONFIG_QUEUE_BW: - err = ops->cfg_q_bw(vf, msg); - break; - case VIRTCHNL_OP_CONFIG_QUANTA: - err = ops->cfg_q_quanta(vf, msg); - break; - case VIRTCHNL_OP_1588_PTP_GET_CAPS: - err = ops->get_ptp_cap(vf, (const void *)msg); - break; - case VIRTCHNL_OP_1588_PTP_GET_TIME: - err = ops->get_phc_time(vf); - break; - case VIRTCHNL_OP_UNKNOWN: - default: - dev_err(dev, "Unsupported opcode %d from VF %d\n", v_opcode, - vf_id); - err = ice_vc_send_msg_to_vf(vf, v_opcode, - VIRTCHNL_STATUS_ERR_NOT_SUPPORTED, - NULL, 0); - break; - } - if (err) { - /* Helper function cares less about error return values here - * as it is busy with pending work. - */ - dev_info(dev, "PF failed to honor VF %d, opcode %d, error %d\n", - vf_id, v_opcode, err); - } - -finish: - mutex_unlock(&vf->cfg_lock); - ice_put_vf(vf); -} -- 2.47.1