@@ -146,6 +146,7 @@ struct vf_data_storage {
u16 vlans_enabled;
bool clear_to_send;
bool pf_set_mac;
+ bool mc_promisc;
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos;
u16 tx_rate;
@@ -73,6 +73,7 @@ enum ixgbe_pfvf_api_rev {
ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */
ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */
ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
+ ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
@@ -91,6 +92,9 @@ enum ixgbe_pfvf_api_rev {
/* mailbox API, version 1.1 VF requests */
#define IXGBE_VF_GET_QUEUES 0x09 /* get queue configuration */
+/* mailbox API, version 1.2 VF requests */
+#define IXGBE_VF_SET_MC_PROMISC 0x0a /* VF requests PF to set MC promiscuous */
+
/* GET_QUEUES return data indices within the mailbox */
#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */
#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */
@@ -105,9 +105,12 @@ static int __ixgbe_enable_sriov(struct ixgbe_adapter *adapter)
adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
IXGBE_FLAG2_RSC_ENABLED);
- /* enable spoof checking for all VFs */
- for (i = 0; i < adapter->num_vfs; i++)
+ 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 */
+ adapter->vfinfo[i].mc_promisc = false;
+ }
return 0;
}
@@ -308,6 +311,40 @@ int ixgbe_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
return ixgbe_pci_sriov_enable(dev, num_vfs);
}
+static int ixgbe_enable_vf_mc_promisc(struct ixgbe_adapter *adapter, u32 vf)
+{
+ struct ixgbe_hw *hw;
+ u32 vmolr;
+
+ hw = &adapter->hw;
+ vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+
+ e_info(drv, "VF %u: enabling multicast promiscuous\n", vf);
+
+ vmolr |= IXGBE_VMOLR_MPE;
+
+ IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
+
+ return 0;
+}
+
+static int ixgbe_disable_vf_mc_promisc(struct ixgbe_adapter *adapter, u32 vf)
+{
+ struct ixgbe_hw *hw;
+ u32 vmolr;
+
+ hw = &adapter->hw;
+ vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+
+ e_info(drv, "VF %u: disabling multicast promiscuous\n", vf);
+
+ vmolr &= ~IXGBE_VMOLR_MPE;
+
+ IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
+
+ return 0;
+}
+
static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
u32 *msgbuf, u32 vf)
{
@@ -322,6 +359,12 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
u32 mta_reg;
u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+ /* Disable multicast promiscuous first */
+ if (adapter->vfinfo[vf].mc_promisc) {
+ ixgbe_disable_vf_mc_promisc(adapter, vf);
+ adapter->vfinfo[vf].mc_promisc = false;
+ }
+
/* only so many hash values supported */
entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES);
@@ -424,6 +467,7 @@ static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
#endif /* CONFIG_FCOE */
switch (adapter->vfinfo[vf].vf_api) {
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
/*
* Version 1.1 supports jumbo frames on VFs if PF has
* jumbo frames enabled which means legacy VFs are
@@ -707,6 +751,12 @@ static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
IXGBE_WRITE_REG(hw, IXGBE_PVFTDWBALn(q_per_pool, vf, i), 0);
}
+ /* Disable multicast promiscuous at reset */
+ if (adapter->vfinfo[vf].mc_promisc) {
+ ixgbe_disable_vf_mc_promisc(adapter, vf);
+ adapter->vfinfo[vf].mc_promisc = false;
+ }
+
/* reply to reset with ack and vf mac address */
msgbuf[0] = IXGBE_VF_RESET;
if (!is_zero_ether_addr(vf_mac)) {
@@ -891,6 +941,12 @@ static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
switch (api) {
case ixgbe_mbox_api_10:
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
+ e_info(drv, "VF %d requested api_version %s\n", vf,
+ (api == ixgbe_mbox_api_12) ? "ixgbe_mbox_api_12" :
+ (api == ixgbe_mbox_api_11) ? "ixgbe_mbox_api_11" :
+ (api == ixgbe_mbox_api_10) ? "ixgbe_mbox_api_10" :
+ "unknown");
adapter->vfinfo[vf].vf_api = api;
return 0;
default:
@@ -914,6 +970,7 @@ static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
switch (adapter->vfinfo[vf].vf_api) {
case ixgbe_mbox_api_20:
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
break;
default:
return -1;
@@ -941,6 +998,30 @@ static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
return 0;
}
+static int ixgbe_set_vf_mc_promisc(struct ixgbe_adapter *adapter,
+ u32 *msgbuf, u32 vf)
+{
+ bool enable = !!msgbuf[1]; /* msgbuf contains the flag to enable */
+
+ switch (adapter->vfinfo[vf].vf_api) {
+ case ixgbe_mbox_api_12:
+ break;
+ default:
+ return -1;
+ }
+
+ /* nothing to do */
+ if (adapter->vfinfo[vf].mc_promisc == enable)
+ return 0;
+
+ adapter->vfinfo[vf].mc_promisc = enable;
+
+ if (enable)
+ return ixgbe_enable_vf_mc_promisc(adapter, vf);
+ else
+ return ixgbe_disable_vf_mc_promisc(adapter, vf);
+}
+
static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
{
u32 mbx_size = IXGBE_VFMAILBOX_SIZE;
@@ -997,6 +1078,9 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
case IXGBE_VF_GET_QUEUES:
retval = ixgbe_get_vf_queues(adapter, msgbuf, vf);
break;
+ case IXGBE_VF_SET_MC_PROMISC:
+ retval = ixgbe_set_vf_mc_promisc(adapter, msgbuf, vf);
+ break;
default:
e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
retval = IXGBE_ERR_MBX;
@@ -2026,7 +2026,8 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
- int api[] = { ixgbe_mbox_api_11,
+ int api[] = { ixgbe_mbox_api_12,
+ ixgbe_mbox_api_11,
ixgbe_mbox_api_10,
ixgbe_mbox_api_unknown };
int err = 0, idx = 0;
@@ -2040,6 +2041,12 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
idx++;
}
+ dev_info(&adapter->pdev->dev, "mbox api_version = %s\n",
+ (hw->api_version == ixgbe_mbox_api_12) ? "ixgbe_mbox_api_12" :
+ (hw->api_version == ixgbe_mbox_api_11) ? "ixgbe_mbox_api_11" :
+ (hw->api_version == ixgbe_mbox_api_10) ? "ixgbe_mbox_api_10" :
+ "unknown");
+
spin_unlock_bh(&adapter->mbx_lock);
}
@@ -2210,6 +2217,9 @@ void ixgbevf_down(struct ixgbevf_adapter *adapter)
IXGBE_TXDCTL_SWFLSH);
}
+ /* drop multicast promiscuous mode flag */
+ adapter->hw.mac.mc_promisc = false;
+
if (!pci_channel_offline(adapter->pdev))
ixgbevf_reset(adapter);
@@ -3712,6 +3722,7 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
switch (adapter->hw.api_version) {
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
break;
default:
@@ -86,6 +86,7 @@ enum ixgbe_pfvf_api_rev {
ixgbe_mbox_api_10, /* API version 1.0, linux/freebsd VF driver */
ixgbe_mbox_api_20, /* API version 2.0, solaris Phase1 VF driver */
ixgbe_mbox_api_11, /* API version 1.1, linux/freebsd VF driver */
+ ixgbe_mbox_api_12, /* API version 1.2, linux/freebsd VF driver */
/* This value should always be last */
ixgbe_mbox_api_unknown, /* indicates that API version is not known */
};
@@ -104,6 +105,9 @@ enum ixgbe_pfvf_api_rev {
/* mailbox API, version 1.1 VF requests */
#define IXGBE_VF_GET_QUEUE 0x09 /* get queue configuration */
+/* mailbox API, version 1.2 VF requests */
+#define IXGBE_VF_SET_MC_PROMISC 0x0a /* VF requests PF to set MC promiscuous */
+
/* GET_QUEUES return data indices within the mailbox */
#define IXGBE_VF_TX_QUEUES 1 /* number of Tx queues supported */
#define IXGBE_VF_RX_QUEUES 2 /* number of Rx queues supported */
@@ -120,6 +120,9 @@ static s32 ixgbevf_reset_hw_vf(struct ixgbe_hw *hw)
memcpy(hw->mac.perm_addr, addr, ETH_ALEN);
hw->mac.mc_filter_type = msgbuf[IXGBE_VF_MC_TYPE_WORD];
+ /* after reset, MC promiscuous mode is disabled */
+ hw->mac.mc_promisc = false;
+
return 0;
}
@@ -327,8 +330,28 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
*/
cnt = netdev_mc_count(netdev);
- if (cnt > 30)
+ if (cnt > 30) {
+ /* If the API has the capability to handle MC promiscuous
+ * mode, turn it on.
+ */
+ if (hw->api_version == ixgbe_mbox_api_12) {
+ if (!hw->mac.mc_promisc) {
+ struct ixgbevf_adapter *adapter = hw->back;
+
+ dev_info(&adapter->pdev->dev, "Request MC PROMISC\n");
+
+ /* enabling multicast promiscuous */
+ msgbuf[0] = IXGBE_VF_SET_MC_PROMISC;
+ msgbuf[1] = 1;
+ ixgbevf_write_msg_read_ack(hw, msgbuf, 2);
+
+ hw->mac.mc_promisc = true;
+ }
+
+ return 0;
+ }
cnt = 30;
+ }
msgbuf[0] = IXGBE_VF_SET_MULTICAST;
msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT;
@@ -344,6 +367,8 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
ixgbevf_write_msg_read_ack(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);
+ hw->mac.mc_promisc = false;
+
return 0;
}
@@ -545,6 +570,7 @@ int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
/* do nothing if API doesn't support ixgbevf_get_queues */
switch (hw->api_version) {
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
break;
default:
return 0;
@@ -87,6 +87,7 @@ struct ixgbe_mac_info {
enum ixgbe_mac_type type;
s32 mc_filter_type;
+ bool mc_promisc;
bool get_link_status;
u32 max_tx_queues;