@@ -150,6 +150,7 @@ struct vf_data_storage {
u16 tx_rate;
u16 vlan_count;
u8 spoofchk_enabled;
+ u8 mc_promisc_allowed;
unsigned int vf_api;
};
@@ -3569,6 +3569,12 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
if (!adapter->vfinfo[i].spoofchk_enabled)
ixgbe_ndo_set_vf_spoofchk(adapter->netdev, i, false);
}
+
+ /* Reconfigure multicast promiscuous mode */
+ for (i = 0; i < adapter->num_vfs; i++) {
+ ixgbe_ndo_set_vf_mc_promisc(adapter->netdev, i,
+ adapter->vfinfo[i].mc_promisc_allowed);
+ }
}
static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
@@ -7955,6 +7961,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_vlan = ixgbe_ndo_set_vf_vlan,
.ndo_set_vf_rate = ixgbe_ndo_set_vf_bw,
.ndo_set_vf_spoofchk = ixgbe_ndo_set_vf_spoofchk,
+ .ndo_set_vf_mc_promisc = ixgbe_ndo_set_vf_mc_promisc,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
#ifdef CONFIG_IXGBE_DCB
@@ -111,8 +111,11 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
for (i = 0; i < adapter->num_vfs; i++) {
/* Enable spoof checking for all VFs */
adapter->vfinfo[i].spoofchk_enabled = true;
- /* Turn multicast promiscuous mode off for all VFs */
+ /*
+ * Disallow VF multicast promiscuous capability
+ * and turn it off for all VFs */
adapter->vfinfo[i].mc_promisc = false;
+ adapter->vfinfo[i].mc_promisc_allowed = false;
}
return 0;
}
@@ -1019,7 +1022,7 @@ static int ixgbe_set_vf_mc_promisc(struct ixgbe_adapter *adapter,
adapter->vfinfo[vf].mc_promisc = enable;
- if (enable)
+ if (enable && adapter->vfinfo[vf].mc_promisc_allowed)
return ixgbe_enable_vf_mc_promisc(adapter, vf);
else
return ixgbe_disable_vf_mc_promisc(adapter, vf);
@@ -1415,6 +1418,32 @@ int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
return 0;
}
+int ixgbe_ndo_set_vf_mc_promisc(struct net_device *netdev, int vf, bool setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 vmolr;
+
+ if (vf >= adapter->num_vfs)
+ return -EINVAL;
+
+ /* nothing to do */
+ if (adapter->vfinfo[vf].mc_promisc_allowed == setting)
+ return 0;
+
+ adapter->vfinfo[vf].mc_promisc_allowed = setting;
+
+ /* if VF requests multicast promiscuous */
+ if (adapter->vfinfo[vf].mc_promisc) {
+ if (setting)
+ ixgbe_enable_vf_mc_promisc(adapter, vf);
+ else
+ ixgbe_disable_vf_mc_promisc(adapter, vf);
+ }
+
+ return 0;
+}
+
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi)
{
@@ -1428,5 +1457,7 @@ int ixgbe_ndo_get_vf_config(struct net_device *netdev,
ivi->vlan = adapter->vfinfo[vf].pf_vlan;
ivi->qos = adapter->vfinfo[vf].pf_qos;
ivi->spoofchk = adapter->vfinfo[vf].spoofchk_enabled;
+ ivi->mc_promisc = adapter->vfinfo[vf].mc_promisc_allowed;
+
return 0;
}
@@ -47,6 +47,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan,
int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int min_tx_rate,
int max_tx_rate);
int ixgbe_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
+int ixgbe_ndo_set_vf_mc_promisc(struct net_device *netdev, int vf, bool setting);
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi);
void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);