@@ -34,6 +34,37 @@ static int ice_check_vf_init(struct ice_pf *pf, struct ice_vf *vf)
3434 return 0 ;
3535}
3636
37+ /**
38+ * ice_err_to_virt_err - translate errors for VF return code
39+ * @ice_err: error return code
40+ */
41+ static enum virtchnl_status_code ice_err_to_virt_err (enum ice_status ice_err )
42+ {
43+ switch (ice_err ) {
44+ case ICE_SUCCESS :
45+ return VIRTCHNL_STATUS_SUCCESS ;
46+ case ICE_ERR_BAD_PTR :
47+ case ICE_ERR_INVAL_SIZE :
48+ case ICE_ERR_DEVICE_NOT_SUPPORTED :
49+ case ICE_ERR_PARAM :
50+ case ICE_ERR_CFG :
51+ return VIRTCHNL_STATUS_ERR_PARAM ;
52+ case ICE_ERR_NO_MEMORY :
53+ return VIRTCHNL_STATUS_ERR_NO_MEMORY ;
54+ case ICE_ERR_NOT_READY :
55+ case ICE_ERR_RESET_FAILED :
56+ case ICE_ERR_FW_API_VER :
57+ case ICE_ERR_AQ_ERROR :
58+ case ICE_ERR_AQ_TIMEOUT :
59+ case ICE_ERR_AQ_FULL :
60+ case ICE_ERR_AQ_NO_WORK :
61+ case ICE_ERR_AQ_EMPTY :
62+ return VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR ;
63+ default :
64+ return VIRTCHNL_STATUS_ERR_NOT_SUPPORTED ;
65+ }
66+ }
67+
3768/**
3869 * ice_vc_vf_broadcast - Broadcast a message to all VFs on PF
3970 * @pf: pointer to the PF structure
@@ -2059,6 +2090,173 @@ int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena)
20592090 return ret ;
20602091}
20612092
2093+ /**
2094+ * ice_is_any_vf_in_promisc - check if any VF(s) are in promiscuous mode
2095+ * @pf: PF structure for accessing VF(s)
2096+ *
2097+ * Return false if no VF(s) are in unicast and/or multicast promiscuous mode,
2098+ * else return true
2099+ */
2100+ bool ice_is_any_vf_in_promisc (struct ice_pf * pf )
2101+ {
2102+ int vf_idx ;
2103+
2104+ ice_for_each_vf (pf , vf_idx ) {
2105+ struct ice_vf * vf = & pf -> vf [vf_idx ];
2106+
2107+ /* found a VF that has promiscuous mode configured */
2108+ if (test_bit (ICE_VF_STATE_UC_PROMISC , vf -> vf_states ) ||
2109+ test_bit (ICE_VF_STATE_MC_PROMISC , vf -> vf_states ))
2110+ return true;
2111+ }
2112+
2113+ return false;
2114+ }
2115+
2116+ /**
2117+ * ice_vc_cfg_promiscuous_mode_msg
2118+ * @vf: pointer to the VF info
2119+ * @msg: pointer to the msg buffer
2120+ *
2121+ * called from the VF to configure VF VSIs promiscuous mode
2122+ */
2123+ static int ice_vc_cfg_promiscuous_mode_msg (struct ice_vf * vf , u8 * msg )
2124+ {
2125+ enum virtchnl_status_code v_ret = VIRTCHNL_STATUS_SUCCESS ;
2126+ struct virtchnl_promisc_info * info =
2127+ (struct virtchnl_promisc_info * )msg ;
2128+ struct ice_pf * pf = vf -> pf ;
2129+ struct ice_vsi * vsi ;
2130+ struct device * dev ;
2131+ bool rm_promisc ;
2132+ int ret = 0 ;
2133+
2134+ if (!test_bit (ICE_VF_STATE_ACTIVE , vf -> vf_states )) {
2135+ v_ret = VIRTCHNL_STATUS_ERR_PARAM ;
2136+ goto error_param ;
2137+ }
2138+
2139+ if (!ice_vc_isvalid_vsi_id (vf , info -> vsi_id )) {
2140+ v_ret = VIRTCHNL_STATUS_ERR_PARAM ;
2141+ goto error_param ;
2142+ }
2143+
2144+ vsi = pf -> vsi [vf -> lan_vsi_idx ];
2145+ if (!vsi ) {
2146+ v_ret = VIRTCHNL_STATUS_ERR_PARAM ;
2147+ goto error_param ;
2148+ }
2149+
2150+ dev = ice_pf_to_dev (pf );
2151+ if (!test_bit (ICE_VIRTCHNL_VF_CAP_PRIVILEGE , & vf -> vf_caps )) {
2152+ dev_err (dev , "Unprivileged VF %d is attempting to configure promiscuous mode\n" ,
2153+ vf -> vf_id );
2154+ /* Leave v_ret alone, lie to the VF on purpose. */
2155+ goto error_param ;
2156+ }
2157+
2158+ rm_promisc = !(info -> flags & FLAG_VF_UNICAST_PROMISC ) &&
2159+ !(info -> flags & FLAG_VF_MULTICAST_PROMISC );
2160+
2161+ if (vsi -> num_vlan || vf -> port_vlan_info ) {
2162+ struct ice_vsi * pf_vsi = ice_get_main_vsi (pf );
2163+ struct net_device * pf_netdev ;
2164+
2165+ if (!pf_vsi ) {
2166+ v_ret = VIRTCHNL_STATUS_ERR_PARAM ;
2167+ goto error_param ;
2168+ }
2169+
2170+ pf_netdev = pf_vsi -> netdev ;
2171+
2172+ ret = ice_set_vf_spoofchk (pf_netdev , vf -> vf_id , rm_promisc );
2173+ if (ret ) {
2174+ dev_err (dev , "Failed to update spoofchk to %s for VF %d VSI %d when setting promiscuous mode\n" ,
2175+ rm_promisc ? "ON" : "OFF" , vf -> vf_id ,
2176+ vsi -> vsi_num );
2177+ v_ret = VIRTCHNL_STATUS_ERR_PARAM ;
2178+ }
2179+
2180+ ret = ice_cfg_vlan_pruning (vsi , true, !rm_promisc );
2181+ if (ret ) {
2182+ dev_err (dev , "Failed to configure VLAN pruning in promiscuous mode\n" );
2183+ v_ret = VIRTCHNL_STATUS_ERR_PARAM ;
2184+ goto error_param ;
2185+ }
2186+ }
2187+
2188+ if (!test_bit (ICE_FLAG_VF_TRUE_PROMISC_ENA , pf -> flags )) {
2189+ bool set_dflt_vsi = !!(info -> flags & FLAG_VF_UNICAST_PROMISC );
2190+
2191+ if (set_dflt_vsi && !ice_is_dflt_vsi_in_use (pf -> first_sw ))
2192+ /* only attempt to set the default forwarding VSI if
2193+ * it's not currently set
2194+ */
2195+ ret = ice_set_dflt_vsi (pf -> first_sw , vsi );
2196+ else if (!set_dflt_vsi &&
2197+ ice_is_vsi_dflt_vsi (pf -> first_sw , vsi ))
2198+ /* only attempt to free the default forwarding VSI if we
2199+ * are the owner
2200+ */
2201+ ret = ice_clear_dflt_vsi (pf -> first_sw );
2202+
2203+ if (ret ) {
2204+ dev_err (dev , "%sable VF %d as the default VSI failed, error %d\n" ,
2205+ set_dflt_vsi ? "en" : "dis" , vf -> vf_id , ret );
2206+ v_ret = VIRTCHNL_STATUS_ERR_ADMIN_QUEUE_ERROR ;
2207+ goto error_param ;
2208+ }
2209+ } else {
2210+ enum ice_status status ;
2211+ u8 promisc_m ;
2212+
2213+ if (info -> flags & FLAG_VF_UNICAST_PROMISC ) {
2214+ if (vf -> port_vlan_info || vsi -> num_vlan )
2215+ promisc_m = ICE_UCAST_VLAN_PROMISC_BITS ;
2216+ else
2217+ promisc_m = ICE_UCAST_PROMISC_BITS ;
2218+ } else if (info -> flags & FLAG_VF_MULTICAST_PROMISC ) {
2219+ if (vf -> port_vlan_info || vsi -> num_vlan )
2220+ promisc_m = ICE_MCAST_VLAN_PROMISC_BITS ;
2221+ else
2222+ promisc_m = ICE_MCAST_PROMISC_BITS ;
2223+ } else {
2224+ if (vf -> port_vlan_info || vsi -> num_vlan )
2225+ promisc_m = ICE_UCAST_VLAN_PROMISC_BITS ;
2226+ else
2227+ promisc_m = ICE_UCAST_PROMISC_BITS ;
2228+ }
2229+
2230+ /* Configure multicast/unicast with or without VLAN promiscuous
2231+ * mode
2232+ */
2233+ status = ice_vf_set_vsi_promisc (vf , vsi , promisc_m , rm_promisc );
2234+ if (status ) {
2235+ dev_err (dev , "%sable Tx/Rx filter promiscuous mode on VF-%d failed, error: %d\n" ,
2236+ rm_promisc ? "dis" : "en" , vf -> vf_id , status );
2237+ v_ret = ice_err_to_virt_err (status );
2238+ goto error_param ;
2239+ } else {
2240+ dev_dbg (dev , "%sable Tx/Rx filter promiscuous mode on VF-%d succeeded\n" ,
2241+ rm_promisc ? "dis" : "en" , vf -> vf_id );
2242+ }
2243+ }
2244+
2245+ if (info -> flags & FLAG_VF_MULTICAST_PROMISC )
2246+ set_bit (ICE_VF_STATE_MC_PROMISC , vf -> vf_states );
2247+ else
2248+ clear_bit (ICE_VF_STATE_MC_PROMISC , vf -> vf_states );
2249+
2250+ if (info -> flags & FLAG_VF_UNICAST_PROMISC )
2251+ set_bit (ICE_VF_STATE_UC_PROMISC , vf -> vf_states );
2252+ else
2253+ clear_bit (ICE_VF_STATE_UC_PROMISC , vf -> vf_states );
2254+
2255+ error_param :
2256+ return ice_vc_send_msg_to_vf (vf , VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE ,
2257+ v_ret , NULL , 0 );
2258+ }
2259+
20622260/**
20632261 * ice_vc_get_stats_msg
20642262 * @vf: pointer to the VF info
@@ -2992,8 +3190,9 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)
29923190 goto error_param ;
29933191 }
29943192
2995- if (test_bit (ICE_VF_STATE_UC_PROMISC , vf -> vf_states ) ||
2996- test_bit (ICE_VF_STATE_MC_PROMISC , vf -> vf_states ))
3193+ if ((test_bit (ICE_VF_STATE_UC_PROMISC , vf -> vf_states ) ||
3194+ test_bit (ICE_VF_STATE_MC_PROMISC , vf -> vf_states )) &&
3195+ test_bit (ICE_FLAG_VF_TRUE_PROMISC_ENA , pf -> flags ))
29973196 vlan_promisc = true;
29983197
29993198 if (add_v ) {
@@ -3317,6 +3516,9 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
33173516 case VIRTCHNL_OP_GET_STATS :
33183517 err = ice_vc_get_stats_msg (vf , msg );
33193518 break ;
3519+ case VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE :
3520+ err = ice_vc_cfg_promiscuous_mode_msg (vf , msg );
3521+ break ;
33203522 case VIRTCHNL_OP_ADD_VLAN :
33213523 err = ice_vc_add_vlan_msg (vf , msg );
33223524 break ;
0 commit comments