diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 945c13d1a982..fd04386a7580 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -833,7 +833,7 @@ void wx_flush_sw_mac_table(struct wx *wx)
 }
 EXPORT_SYMBOL(wx_flush_sw_mac_table);
 
-static int wx_add_mac_filter(struct wx *wx, u8 *addr, u16 pool)
+int wx_add_mac_filter(struct wx *wx, u8 *addr, u16 pool)
 {
 	u32 i;
 
@@ -863,8 +863,9 @@ static int wx_add_mac_filter(struct wx *wx, u8 *addr, u16 pool)
 	}
 	return -ENOMEM;
 }
+EXPORT_SYMBOL(wx_add_mac_filter);
 
-static int wx_del_mac_filter(struct wx *wx, u8 *addr, u16 pool)
+int wx_del_mac_filter(struct wx *wx, u8 *addr, u16 pool)
 {
 	u32 i;
 
@@ -887,6 +888,7 @@ static int wx_del_mac_filter(struct wx *wx, u8 *addr, u16 pool)
 	}
 	return -ENOMEM;
 }
+EXPORT_SYMBOL(wx_del_mac_filter);
 
 static int wx_available_rars(struct wx *wx)
 {
@@ -2080,7 +2082,7 @@ static int wx_set_vlvf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on,
  *
  *  Turn on/off specified VLAN in the VLAN filter table.
  **/
-static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on)
+int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on)
 {
 	u32 bitindex, vfta, targetbit;
 	bool vfta_changed = false;
@@ -2126,6 +2128,7 @@ static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on)
 
 	return 0;
 }
+EXPORT_SYMBOL(wx_set_vfta);
 
 /**
  *  wx_clear_vfta - Clear VLAN filter table
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
index 9e219fa717a2..f2717fdf83cd 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h
@@ -25,6 +25,8 @@ void wx_init_eeprom_params(struct wx *wx);
 void wx_get_mac_addr(struct wx *wx, u8 *mac_addr);
 void wx_init_rx_addrs(struct wx *wx);
 void wx_mac_set_default_filter(struct wx *wx, u8 *addr);
+int wx_add_mac_filter(struct wx *wx, u8 *addr, u16 pool);
+int wx_del_mac_filter(struct wx *wx, u8 *addr, u16 pool);
 void wx_flush_sw_mac_table(struct wx *wx);
 int wx_set_mac(struct net_device *netdev, void *p);
 void wx_disable_rx(struct wx *wx);
@@ -39,6 +41,7 @@ int wx_stop_adapter(struct wx *wx);
 void wx_reset_misc(struct wx *wx);
 int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count);
 int wx_sw_init(struct wx *wx);
+int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on);
 int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid);
 int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid);
 int wx_fc_enable(struct wx *wx, bool tx_pause, bool rx_pause);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_mbx.h b/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
index 3c70654a8b14..201efbc2db9a 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_mbx.h
@@ -21,8 +21,11 @@
 #define WX_MBVFICR_VFREQ_MASK GENMASK(15, 0)
 #define WX_MBVFICR_VFACK_MASK GENMASK(31, 16)
 
+#define WX_VT_MSGTYPE_CTS     BIT(29)
 #define WX_VT_MSGINFO_MASK    GENMASK(23, 16)
 
+#define WX_PF_CONTROL_MSG            BIT(8) /* PF control message */
+
 enum wxvf_xcast_modes {
 	WXVF_XCAST_MODE_NONE = 0,
 };
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c
index 032b75f23460..decef4af3ee4 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c
@@ -5,6 +5,7 @@
 #include <linux/pci.h>
 
 #include "wx_type.h"
+#include "wx_hw.h"
 #include "wx_mbx.h"
 #include "wx_sriov.h"
 
@@ -219,3 +220,353 @@ int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
 	return num_vfs;
 }
 EXPORT_SYMBOL(wx_pci_sriov_configure);
+
+int wx_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi)
+{
+	struct wx *wx = netdev_priv(netdev);
+
+	if (vf >= wx->num_vfs)
+		return -EINVAL;
+	ivi->vf = vf;
+	memcpy(&ivi->mac, wx->vfinfo[vf].vf_mac_addr, ETH_ALEN);
+
+	ivi->vlan = wx->vfinfo[vf].pf_vlan;
+	ivi->qos = wx->vfinfo[vf].pf_qos;
+	ivi->spoofchk = wx->vfinfo[vf].spoofchk_enabled;
+
+	ivi->trusted = wx->vfinfo[vf].trusted;
+	ivi->linkstate = wx->vfinfo[vf].link_state;
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_ndo_get_vf_config);
+
+static int wx_set_vf_mac(struct wx *wx, u16 vf, unsigned char *mac_addr)
+{
+	int ret = 0;
+
+	wx_del_mac_filter(wx, wx->vfinfo[vf].vf_mac_addr, vf);
+	ret = wx_add_mac_filter(wx, mac_addr, vf);
+	if (ret >= 0)
+		memcpy(wx->vfinfo[vf].vf_mac_addr, mac_addr, ETH_ALEN);
+	else
+		memset(wx->vfinfo[vf].vf_mac_addr, 0, ETH_ALEN);
+
+	return ret;
+}
+
+int wx_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
+{
+	struct wx *wx = netdev_priv(netdev);
+	int retval = 0;
+
+	if (!is_valid_ether_addr(mac) || vf >= wx->num_vfs)
+		return -EINVAL;
+
+	retval = wx_set_vf_mac(wx, vf, mac);
+	if (retval >= 0) {
+		wx->vfinfo[vf].pf_set_mac = true;
+		if (!netif_running(wx->netdev))
+			wx_err(wx, "Bring the PF device up before use vfs\n");
+	} else {
+		wx_err(wx, "The VF MAC address was NOT set due to invalid\n");
+	}
+
+	return retval;
+}
+EXPORT_SYMBOL(wx_ndo_set_vf_mac);
+
+static void wx_set_vmolr(struct wx *wx, u16 vf, bool aupe)
+{
+	u32 vmolr = rd32(wx, WX_PSR_VM_L2CTL(vf));
+
+	vmolr |=  WX_PSR_VM_L2CTL_BAM;
+	if (aupe)
+		vmolr |= WX_PSR_VM_L2CTL_AUPE;
+	else
+		vmolr &= ~WX_PSR_VM_L2CTL_AUPE;
+	wr32(wx, WX_PSR_VM_L2CTL(vf), vmolr);
+}
+
+static void wx_set_vmvir(struct wx *wx, u16 vid, u16 qos, u16 vf)
+{
+	u32 vmvir = vid | (qos << VLAN_PRIO_SHIFT) |
+		    WX_TDM_VLAN_INS_VLANA_DEFAULT;
+
+	wr32(wx, WX_TDM_VLAN_INS(vf), vmvir);
+}
+
+static int wx_set_vf_vlan(struct wx *wx, int add, int vid, u16 vf)
+{
+	/* VLAN 0 is a special case, don't allow it to be removed */
+	if (!vid && !add)
+		return 0;
+
+	return wx_set_vfta(wx, vid, vf, (bool)add);
+}
+
+/**
+ *  wx_set_vlan_anti_spoofing - Enable/Disable VLAN anti-spoofing
+ *  @wx: pointer to hardware structure
+ *  @enable: enable or disable switch for VLAN anti-spoofing
+ *  @vf: Virtual Function pool - VF Pool to set for VLAN anti-spoofing
+ *
+ **/
+static void wx_set_vlan_anti_spoofing(struct wx *wx, bool enable, int vf)
+{
+	u32 index = vf / 32, vf_bit = vf % 32;
+	u32 pfvfspoof;
+
+	pfvfspoof = rd32(wx, WX_TDM_VLAN_AS(index));
+	if (enable)
+		pfvfspoof |= BIT(vf_bit);
+	else
+		pfvfspoof &= ~BIT(vf_bit);
+	wr32(wx, WX_TDM_VLAN_AS(index), pfvfspoof);
+}
+
+static inline void wx_write_qde(struct wx *wx, u32 vf, u32 qde)
+{
+	struct wx_ring_feature *vmdq = &wx->ring_feature[RING_F_VMDQ];
+	u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask);
+	u32 reg = 0, n = vf * q_per_pool / 32;
+	u32 i = vf * q_per_pool;
+
+	reg = rd32(wx, WX_RDM_PF_QDE(n));
+	for (i = (vf * q_per_pool - n * 32);
+	     i < ((vf + 1) * q_per_pool - n * 32);
+	     i++) {
+		if (qde == 1)
+			reg |= qde << i;
+		else
+			reg &= qde << i;
+	}
+
+	wr32(wx, WX_RDM_PF_QDE(n), reg);
+}
+
+static inline void wx_write_hide_vlan(struct wx *wx, u32 vf, u32 hide_vlan)
+{
+	struct wx_ring_feature *vmdq = &wx->ring_feature[RING_F_VMDQ];
+	u32 q_per_pool = __ALIGN_MASK(1, ~vmdq->mask);
+	u32 reg = 0, i = vf * q_per_pool;
+	u32 n = i / 32;
+
+	reg = rd32(wx, WX_RDM_PF_HIDE(n));
+	for (i = (vf * q_per_pool - n * 32);
+	     i < ((vf + 1) * q_per_pool - n * 32);
+	     i++) {
+		if (hide_vlan == 1)
+			reg |= hide_vlan << i;
+		else
+			reg &= hide_vlan << i;
+	}
+
+	wr32(wx, WX_RDM_PF_HIDE(n), reg);
+}
+
+static int wx_enable_port_vlan(struct wx *wx, int vf, u16 vlan, u8 qos)
+{
+	int err = 0;
+
+	err = wx_set_vf_vlan(wx, true, vlan, vf);
+	if (err)
+		return err;
+	wx_set_vmvir(wx, vlan, qos, vf);
+	wx_set_vmolr(wx, vf, false);
+	if (wx->vfinfo[vf].spoofchk_enabled)
+		wx_set_vlan_anti_spoofing(wx, true, vf);
+	wx->vfinfo[vf].vlan_count++;
+	/* enable hide vlan */
+	wx_write_qde(wx, vf, 1);
+	wx_write_hide_vlan(wx, vf, 1);
+	wx->vfinfo[vf].pf_vlan = vlan;
+	wx->vfinfo[vf].pf_qos = qos;
+
+	return err;
+}
+
+static void wx_clear_vmvir(struct wx *wx, u32 vf)
+{
+	wr32(wx, WX_TDM_VLAN_INS(vf), 0);
+}
+
+static int wx_disable_port_vlan(struct wx *wx, int vf)
+{
+	int err;
+
+	err = wx_set_vf_vlan(wx, false, wx->vfinfo[vf].pf_vlan, vf);
+	wx_clear_vmvir(wx, vf);
+	wx_set_vmolr(wx, vf, true);
+	wx_set_vlan_anti_spoofing(wx, false, vf);
+	if (wx->vfinfo[vf].vlan_count)
+		wx->vfinfo[vf].vlan_count--;
+	/* disable hide vlan */
+	wx_write_hide_vlan(wx, vf, 0);
+	wx->vfinfo[vf].pf_vlan = 0;
+	wx->vfinfo[vf].pf_qos = 0;
+
+	return err;
+}
+
+int wx_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan,
+		       u8 qos, __be16 vlan_proto)
+{
+	struct wx *wx = netdev_priv(netdev);
+	int err = 0;
+
+	/* VLAN IDs accepted range 0-4094 */
+	if (vf >= wx->num_vfs || vlan > VLAN_VID_MASK - 1 || qos > 7)
+		return -EINVAL;
+
+	if (vlan || qos) {
+		/* Check if there is already a port VLAN set, if so
+		 * we have to delete the old one first before we
+		 * can set the new one.  The usage model had
+		 * previously assumed the user would delete the
+		 * old port VLAN before setting a new one but this
+		 * is not necessarily the case.
+		 */
+		if (wx->vfinfo[vf].pf_vlan) {
+			err = wx_disable_port_vlan(wx, vf);
+			if (err)
+				return err;
+		}
+		err = wx_enable_port_vlan(wx, vf, vlan, qos);
+
+	} else {
+		err = wx_disable_port_vlan(wx, vf);
+	}
+
+	return err;
+}
+EXPORT_SYMBOL(wx_ndo_set_vf_vlan);
+
+int wx_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
+{
+	u32 index = vf / 32, vf_bit = vf % 32;
+	struct wx *wx = netdev_priv(netdev);
+	u32 regval;
+
+	if (vf >= wx->num_vfs)
+		return -EINVAL;
+
+	wx->vfinfo[vf].spoofchk_enabled = setting;
+
+	regval = (setting << vf_bit);
+	wr32m(wx, WX_TDM_MAC_AS(index), regval | BIT(vf_bit), regval);
+
+	if (wx->vfinfo[vf].vlan_count)
+		wr32m(wx, WX_TDM_VLAN_AS(index), regval | BIT(vf_bit), regval);
+
+	return 0;
+}
+EXPORT_SYMBOL(wx_ndo_set_vf_spoofchk);
+
+static inline void wx_ping_vf(struct wx *wx, int vf)
+{
+	u32 ping;
+
+	ping = WX_PF_CONTROL_MSG;
+	if (wx->vfinfo[vf].clear_to_send)
+		ping |= WX_VT_MSGTYPE_CTS;
+	wx_write_mbx_pf(wx, &ping, 1, vf);
+}
+
+/**
+ * wx_set_vf_rx_tx - Set VF rx tx
+ * @wx: Pointer to wx struct
+ * @vf: VF identifier
+ *
+ * Set or reset correct transmit and receive for vf
+ **/
+static void wx_set_vf_rx_tx(struct wx *wx, int vf)
+{
+	u32 reg_cur_tx, reg_cur_rx, reg_req_tx, reg_req_rx;
+	u32 index, vf_bit;
+
+	vf_bit = vf % 32;
+	index = vf / 32;
+
+	reg_cur_tx = rd32(wx, WX_TDM_VF_TE(index));
+	reg_cur_rx = rd32(wx, WX_RDM_VF_RE(index));
+
+	if (wx->vfinfo[vf].link_enable) {
+		reg_req_tx = reg_cur_tx | BIT(vf_bit);
+		reg_req_rx = reg_cur_rx | BIT(vf_bit);
+		/* Enable particular VF */
+		if (reg_cur_tx != reg_req_tx)
+			wr32(wx, WX_TDM_VF_TE(index), reg_req_tx);
+		if (reg_cur_rx != reg_req_rx)
+			wr32(wx, WX_RDM_VF_RE(index), reg_req_rx);
+	} else {
+		reg_req_tx = BIT(vf_bit);
+		reg_req_rx = BIT(vf_bit);
+		/* Disable particular VF */
+		if (reg_cur_tx & reg_req_tx)
+			wr32(wx, WX_TDM_VFTE_CLR(index), reg_req_tx);
+		if (reg_cur_rx & reg_req_rx)
+			wr32(wx, WX_RDM_VFRE_CLR(index), reg_req_rx);
+	}
+}
+
+static void wx_set_vf_link_state(struct wx *wx, int vf, int state)
+{
+	wx->vfinfo[vf].link_state = state;
+	switch (state) {
+	case IFLA_VF_LINK_STATE_AUTO:
+		if (netif_running(wx->netdev))
+			wx->vfinfo[vf].link_enable = true;
+		else
+			wx->vfinfo[vf].link_enable = false;
+		break;
+	case IFLA_VF_LINK_STATE_ENABLE:
+		wx->vfinfo[vf].link_enable = true;
+		break;
+	case IFLA_VF_LINK_STATE_DISABLE:
+		wx->vfinfo[vf].link_enable = false;
+		break;
+	}
+	/* restart the VF */
+	wx->vfinfo[vf].clear_to_send = false;
+	wx_ping_vf(wx, vf);
+
+	wx_set_vf_rx_tx(wx, vf);
+}
+
+/**
+ * wx_ndo_set_vf_link_state - Set link state
+ * @netdev: network interface device structure
+ * @vf: VF identifier
+ * @state: required link state
+ *
+ * Set the link state of a specified VF, regardless of physical link state
+ **/
+int wx_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state)
+{
+	struct wx *wx = netdev_priv(netdev);
+	int ret = 0;
+
+	if (vf < 0 || vf >= wx->num_vfs) {
+		wx_err(wx, "NDO set VF link - invalid VF identifier %d\n", vf);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	switch (state) {
+	case IFLA_VF_LINK_STATE_ENABLE:
+		wx_err(wx, "NDO set VF %d link state %d - not supported\n",
+		       vf, state);
+		break;
+	case IFLA_VF_LINK_STATE_DISABLE:
+	case IFLA_VF_LINK_STATE_AUTO:
+		wx_set_vf_link_state(wx, vf, state);
+		break;
+	default:
+		wx_err(wx, "NDO set VF %d - invalid link state %d\n", vf, state);
+		ret = -EINVAL;
+	}
+out:
+	return ret;
+}
+EXPORT_SYMBOL(wx_ndo_set_vf_link_state);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.h b/drivers/net/ethernet/wangxun/libwx/wx_sriov.h
index 17b547ae8862..6ee1fdff492b 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.h
@@ -6,5 +6,10 @@
 
 int wx_disable_sriov(struct wx *wx);
 int wx_pci_sriov_configure(struct pci_dev *pdev, int num_vfs);
+int wx_ndo_get_vf_config(struct net_device *netdev, int vf, struct ifla_vf_info *ivi);
+int wx_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos, __be16 vlan_proto);
+int wx_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac);
+int wx_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
+int wx_ndo_set_vf_link_state(struct net_device *netdev, int vf, int state);
 
 #endif /* _WX_SRIOV_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index c1bf8653b900..2e2b997f4572 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -75,6 +75,10 @@
 #define WX_MAC_LXONOFFRXC            0x11E0C
 
 /*********************** Receive DMA registers **************************/
+#define WX_RDM_VF_RE(_i)             (0x12004 + ((_i) * 4))
+#define WX_RDM_PF_QDE(_i)            (0x12080 + ((_i) * 4))
+#define WX_RDM_PF_HIDE(_i)           (0x12090 + ((_i) * 4))
+#define WX_RDM_VFRE_CLR(_i)          (0x120A0 + ((_i) * 4))
 #define WX_RDM_DRP_PKT               0x12500
 #define WX_RDM_PKT_CNT               0x12504
 #define WX_RDM_BYTE_CNT_LSB          0x12508
@@ -114,6 +118,9 @@
 /*********************** Transmit DMA registers **************************/
 /* transmit global control */
 #define WX_TDM_CTL                   0x18000
+#define WX_TDM_VF_TE(_i)             (0x18004 + ((_i) * 4))
+#define WX_TDM_VFTE_CLR(_i)          (0x180A0 + ((_i) * 4))
+
 /* TDM CTL BIT */
 #define WX_TDM_CTL_TE                BIT(0) /* Transmit Enable */
 #define WX_TDM_PB_THRE(_i)           (0x18020 + ((_i) * 4))
@@ -244,6 +251,15 @@
 #define WX_RSC_ST                    0x17004
 #define WX_RSC_ST_RSEC_RDY           BIT(0)
 
+/*********************** Transmit DMA registers **************************/
+/* transmit global control */
+#define WX_TDM_ETYPE_AS(_i)          (0x18058 + ((_i) * 4))
+#define WX_TDM_MAC_AS(_i)            (0x18060 + ((_i) * 4))
+#define WX_TDM_VLAN_AS(_i)           (0x18070 + ((_i) * 4))
+#define WX_TDM_VLAN_INS(_i)          (0x18100 + ((_i) * 4))
+/* Per VF Port VLAN insertion rules */
+#define WX_TDM_VLAN_INS_VLANA_DEFAULT BIT(30) /* Always use default VLAN*/
+
 /****************************** TDB ******************************************/
 #define WX_TDB_PB_SZ(_i)             (0x1CC00 + ((_i) * 4))
 #define WX_TXPKT_SIZE_MAX            0xA /* Max Tx Packet size */
@@ -1000,6 +1016,13 @@ struct vf_data_storage {
 	bool link_enable;
 	bool trusted;
 	int xcast_mode;
+	bool clear_to_send;
+	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
+	u16 pf_qos;
+	bool pf_set_mac;
+
+	u16 vlan_count;
+	int link_state;
 };
 
 struct vf_macvlans {
