#include <net/addrconf.h>
 #include <linux/inetdevice.h>
 #include <rdma/ib_cache.h>
+#include <linux/pci.h>
 
 #define DRV_VERSION "1.0.0"
 
        priv->tx_ring = NULL;
 }
 
+static int ipoib_set_vf_link_state(struct net_device *dev, int vf, int link_state)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       return ib_set_vf_link_state(priv->ca, vf, priv->port, link_state);
+}
+
+static int ipoib_get_vf_config(struct net_device *dev, int vf,
+                              struct ifla_vf_info *ivf)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+       int err;
+
+       err = ib_get_vf_config(priv->ca, vf, priv->port, ivf);
+       if (err)
+               return err;
+
+       ivf->vf = vf;
+
+       return 0;
+}
+
+static int ipoib_set_vf_guid(struct net_device *dev, int vf, u64 guid, int type)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       if (type != IFLA_VF_IB_NODE_GUID && type != IFLA_VF_IB_PORT_GUID)
+               return -EINVAL;
+
+       return ib_set_vf_guid(priv->ca, vf, priv->port, guid, type);
+}
+
+static int ipoib_get_vf_stats(struct net_device *dev, int vf,
+                             struct ifla_vf_stats *vf_stats)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+       return ib_get_vf_stats(priv->ca, vf, priv->port, vf_stats);
+}
+
 static const struct header_ops ipoib_header_ops = {
        .create = ipoib_hard_header,
 };
 
-static const struct net_device_ops ipoib_netdev_ops = {
+static const struct net_device_ops ipoib_netdev_ops_pf = {
+       .ndo_uninit              = ipoib_uninit,
+       .ndo_open                = ipoib_open,
+       .ndo_stop                = ipoib_stop,
+       .ndo_change_mtu          = ipoib_change_mtu,
+       .ndo_fix_features        = ipoib_fix_features,
+       .ndo_start_xmit          = ipoib_start_xmit,
+       .ndo_tx_timeout          = ipoib_timeout,
+       .ndo_set_rx_mode         = ipoib_set_mcast_list,
+       .ndo_get_iflink          = ipoib_get_iflink,
+       .ndo_set_vf_link_state   = ipoib_set_vf_link_state,
+       .ndo_get_vf_config       = ipoib_get_vf_config,
+       .ndo_get_vf_stats        = ipoib_get_vf_stats,
+       .ndo_set_vf_guid         = ipoib_set_vf_guid,
+};
+
+static const struct net_device_ops ipoib_netdev_ops_vf = {
        .ndo_uninit              = ipoib_uninit,
        .ndo_open                = ipoib_open,
        .ndo_stop                = ipoib_stop,
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
 
-       dev->netdev_ops          = &ipoib_netdev_ops;
+       if (priv->hca_caps & IB_DEVICE_VIRTUAL_FUNCTION)
+               dev->netdev_ops = &ipoib_netdev_ops_vf;
+       else
+               dev->netdev_ops = &ipoib_netdev_ops_pf;
+
        dev->header_ops          = &ipoib_header_ops;
 
        ipoib_set_ethtool_ops(dev);