#define IXGBE_MAX_VFTA (128)
#define IXGBE_VF_MSG_SIZE_DEFAULT 1
#define IXGBE_VF_GET_QUEUE_MSG_SIZE 5
+#define IXGBE_ETHERTYPE_FLOW_CTRL 0x8808
static inline uint16_t
dev_num_vf(struct rte_eth_dev *eth_dev)
return;
}
+void ixgbe_pf_host_uninit(struct rte_eth_dev *eth_dev)
+{
+ struct ixgbe_vf_info **vfinfo;
+ uint16_t vf_num;
+
+ PMD_INIT_FUNC_TRACE();
+
+ vfinfo = IXGBE_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private);
+
+ RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
+ RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = 0;
+ RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = 0;
+ RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = 0;
+
+ vf_num = dev_num_vf(eth_dev);
+ if (vf_num == 0)
+ return;
+
+ rte_free(*vfinfo);
+ *vfinfo = NULL;
+}
+
+static void
+ixgbe_add_tx_flow_control_drop_filter(struct rte_eth_dev *eth_dev)
+{
+ struct ixgbe_hw *hw =
+ IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+ struct ixgbe_filter_info *filter_info =
+ IXGBE_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private);
+ uint16_t vf_num;
+ int i;
+
+ if (!hw->mac.ops.set_ethertype_anti_spoofing) {
+ RTE_LOG(INFO, PMD, "ether type anti-spoofing is not"
+ " supported.\n");
+ return;
+ }
+
+ /* occupy an entity of ether type filter */
+ for (i = 0; i < IXGBE_MAX_ETQF_FILTERS; i++) {
+ if (!(filter_info->ethertype_mask & (1 << i))) {
+ filter_info->ethertype_mask |= 1 << i;
+ filter_info->ethertype_filters[i] =
+ IXGBE_ETHERTYPE_FLOW_CTRL;
+ break;
+ }
+ }
+ if (i == IXGBE_MAX_ETQF_FILTERS) {
+ RTE_LOG(ERR, PMD, "Cannot find an unused ether type filter"
+ " entity for flow control.\n");
+ return;
+ }
+
+ IXGBE_WRITE_REG(hw, IXGBE_ETQF(i),
+ (IXGBE_ETQF_FILTER_EN |
+ IXGBE_ETQF_TX_ANTISPOOF |
+ IXGBE_ETHERTYPE_FLOW_CTRL));
+
+ vf_num = dev_num_vf(eth_dev);
+ for (i = 0; i < vf_num; i++)
+ hw->mac.ops.set_ethertype_anti_spoofing(hw, true, i);
+}
+
int ixgbe_pf_host_configure(struct rte_eth_dev *eth_dev)
{
uint32_t vtctl, fcrth;
* enable vlan filtering and allow all vlan tags through
*/
vlanctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
- vlanctrl |= IXGBE_VLNCTRL_VFE ; /* enable vlan filters */
+ vlanctrl |= IXGBE_VLNCTRL_VFE; /* enable vlan filters */
IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlanctrl);
/* VFTA - enable all vlan filters */
IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), fcrth);
}
+ ixgbe_add_tx_flow_control_drop_filter(eth_dev);
+
return 0;
}
ixgbe_vf_reset_event(dev, vf);
}
+static int
+ixgbe_enable_vf_mc_promisc(struct rte_eth_dev *dev, uint32_t vf)
+{
+ struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t vmolr;
+
+ vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+
+ RTE_LOG(INFO, PMD, "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 rte_eth_dev *dev, uint32_t vf)
+{
+ struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t vmolr;
+
+ vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
+
+ RTE_LOG(INFO, PMD, "VF %u: disabling multicast promiscuous\n", vf);
+
+ vmolr &= ~IXGBE_VMOLR_MPE;
+
+ IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
+
+ return 0;
+}
+
static int
ixgbe_vf_reset(struct rte_eth_dev *dev, uint16_t vf, uint32_t *msgbuf)
{
hw->mac.ops.set_rar(hw, rar_entry, vf_mac, vf, IXGBE_RAH_AV);
+ /* Disable multicast promiscuous at reset */
+ ixgbe_disable_vf_mc_promisc(dev, vf);
+
/* reply to reset with ack and vf mac address */
msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
rte_memcpy(new_mac, vf_mac, ETHER_ADDR_LEN);
uint32_t reg_val;
int i;
+ /* Disable multicast promiscuous first */
+ ixgbe_disable_vf_mc_promisc(dev, vf);
+
/* only so many hash values supported */
nb_entries = RTE_MIN(nb_entries, IXGBE_MAX_VF_MC_ENTRIES);
/* X540 and X550 support jumbo frames in IOV mode */
if (hw->mac.type != ixgbe_mac_X540 &&
hw->mac.type != ixgbe_mac_X550 &&
- hw->mac.type != ixgbe_mac_X550EM_x)
+ hw->mac.type != ixgbe_mac_X550EM_x &&
+ hw->mac.type != ixgbe_mac_X550EM_a)
return -1;
if ((max_frame < ETHER_MIN_LEN) || (max_frame > ETHER_MAX_JUMBO_FRAME_LEN))
switch (api_version) {
case ixgbe_mbox_api_10:
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
vfinfo[vf].api_version = (uint8_t)api_version;
return 0;
default:
switch (vfinfo[vf].api_version) {
case ixgbe_mbox_api_20:
case ixgbe_mbox_api_11:
+ case ixgbe_mbox_api_12:
break;
default:
return -1;
return 0;
}
+static int
+ixgbe_set_vf_mc_promisc(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf)
+{
+ struct ixgbe_vf_info *vfinfo =
+ *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
+ bool enable = !!msgbuf[1]; /* msgbuf contains the flag to enable */
+
+ switch (vfinfo[vf].api_version) {
+ case ixgbe_mbox_api_12:
+ break;
+ default:
+ return -1;
+ }
+
+ if (enable)
+ return ixgbe_enable_vf_mc_promisc(dev, vf);
+ else
+ return ixgbe_disable_vf_mc_promisc(dev, vf);
+}
+
static int
ixgbe_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf)
{
retval = ixgbe_get_vf_queues(dev, vf, msgbuf);
msg_size = IXGBE_VF_GET_QUEUE_MSG_SIZE;
break;
+ case IXGBE_VF_UPDATE_XCAST_MODE:
+ retval = ixgbe_set_vf_mc_promisc(dev, vf, msgbuf);
+ break;
default:
PMD_DRV_LOG(DEBUG, "Unhandled Msg %8.8x", (unsigned)msgbuf[0]);
retval = IXGBE_ERR_MBX;