diff mbox

[net-next,V2,2/2] intel: ixgbevf: Support Windows hosts (Hyper-V)

Message ID 1460956969-17601-3-git-send-email-kys@microsoft.com
State Awaiting Upstream, archived
Delegated to: David Miller
Headers show

Commit Message

KY Srinivasan April 18, 2016, 5:22 a.m. UTC
On Hyper-V, the VF/PF communication is a via software mediated path
as opposed to the hardware mailbox. Make the necessary
adjustments to support Hyper-V.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
---
	V2: Addressed most of the comments from
	    Alexander Duyck <alexander.duyck@gmail.com>
	    and Rustad, Mark D <mark.d.rustad@intel.com>.

 drivers/net/ethernet/intel/ixgbevf/ixgbevf.h      |   12 ++
 drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   16 ++-
 drivers/net/ethernet/intel/ixgbevf/mbx.c          |   12 ++
 drivers/net/ethernet/intel/ixgbevf/vf.c           |  201 +++++++++++++++++++++
 4 files changed, 237 insertions(+), 4 deletions(-)

Comments

Alexander H Duyck April 18, 2016, 4:17 p.m. UTC | #1
On Sun, Apr 17, 2016 at 10:22 PM, K. Y. Srinivasan <kys@microsoft.com> wrote:
> On Hyper-V, the VF/PF communication is a via software mediated path
> as opposed to the hardware mailbox. Make the necessary
> adjustments to support Hyper-V.
>
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> ---
>         V2: Addressed most of the comments from
>             Alexander Duyck <alexander.duyck@gmail.com>
>             and Rustad, Mark D <mark.d.rustad@intel.com>.
>
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf.h      |   12 ++
>  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   16 ++-
>  drivers/net/ethernet/intel/ixgbevf/mbx.c          |   12 ++
>  drivers/net/ethernet/intel/ixgbevf/vf.c           |  201 +++++++++++++++++++++
>  4 files changed, 237 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
> index 5ac60ee..3296d27 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
> @@ -460,9 +460,13 @@ enum ixbgevf_state_t {
>
>  enum ixgbevf_boards {
>         board_82599_vf,
> +       board_82599_vf_hv,
>         board_X540_vf,
> +       board_X540_vf_hv,
>         board_X550_vf,
> +       board_X550_vf_hv,
>         board_X550EM_x_vf,
> +       board_X550EM_x_vf_hv,
>  };
>
>  enum ixgbevf_xcast_modes {
> @@ -477,6 +481,13 @@ extern const struct ixgbevf_info ixgbevf_X550_vf_info;
>  extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_info;
>  extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
>
> +
> +extern const struct ixgbevf_info ixgbevf_82599_vf_hv_info;
> +extern const struct ixgbevf_info ixgbevf_X540_vf_hv_info;
> +extern const struct ixgbevf_info ixgbevf_X550_vf_hv_info;
> +extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info;
> +extern const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops;
> +
>  /* needed by ethtool.c */
>  extern const char ixgbevf_driver_name[];
>  extern const char ixgbevf_driver_version[];
> @@ -494,6 +505,7 @@ void ixgbevf_free_rx_resources(struct ixgbevf_ring *);
>  void ixgbevf_free_tx_resources(struct ixgbevf_ring *);
>  void ixgbevf_update_stats(struct ixgbevf_adapter *adapter);
>  int ethtool_ioctl(struct ifreq *ifr);
> +bool ixgbevf_on_hyperv(struct ixgbe_hw *hw);
>
>  extern void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector);
>
> diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> index 007cbe0..c761d80 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
> @@ -62,10 +62,14 @@ static char ixgbevf_copyright[] =
>         "Copyright (c) 2009 - 2015 Intel Corporation.";
>
>  static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
> -       [board_82599_vf] = &ixgbevf_82599_vf_info,
> -       [board_X540_vf]  = &ixgbevf_X540_vf_info,
> -       [board_X550_vf]  = &ixgbevf_X550_vf_info,
> -       [board_X550EM_x_vf] = &ixgbevf_X550EM_x_vf_info,
> +       [board_82599_vf]        = &ixgbevf_82599_vf_info,
> +       [board_82599_vf_hv]     = &ixgbevf_82599_vf_hv_info,
> +       [board_X540_vf]         = &ixgbevf_X540_vf_info,
> +       [board_X540_vf_hv]      = &ixgbevf_X540_vf_hv_info,
> +       [board_X550_vf]         = &ixgbevf_X550_vf_info,
> +       [board_X550_vf_hv]      = &ixgbevf_X550_vf_hv_info,
> +       [board_X550EM_x_vf]     = &ixgbevf_X550EM_x_vf_info,
> +       [board_X550EM_x_vf_hv]  = &ixgbevf_X550EM_x_vf_hv_info,
>  };
>
>  /* ixgbevf_pci_tbl - PCI Device ID Table
> @@ -78,9 +82,13 @@ static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
>   */
>  static const struct pci_device_id ixgbevf_pci_tbl[] = {
>         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf },
> +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF_HV), board_82599_vf_hv },
>         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf },
> +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF_HV), board_X540_vf_hv },
>         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF), board_X550_vf },
> +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF_HV), board_X550_vf_hv },
>         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF), board_X550EM_x_vf },
> +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV), board_X550EM_x_vf_hv},
>         /* required last entry */
>         {0, }
>  };
> diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
> index dc68fea..298a0da 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/mbx.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
> @@ -346,3 +346,15 @@ const struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
>         .check_for_rst  = ixgbevf_check_for_rst_vf,
>  };
>
> +/**
> + * Mailbox operations when running on Hyper-V.
> + * On Hyper-V, PF/VF communiction is not through the
> + * hardware mailbox; this communication is through
> + * a software mediated path.
> + * Most mail box operations are noop while running on
> + * Hyper-V.
> + */
> +const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops = {
> +       .init_params    = ixgbevf_init_mbx_params_vf,
> +       .check_for_rst  = ixgbevf_check_for_rst_vf,
> +};
> diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
> index 4d613a4..1ec13c1 100644
> --- a/drivers/net/ethernet/intel/ixgbevf/vf.c
> +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
> @@ -27,6 +27,13 @@
>  #include "vf.h"
>  #include "ixgbevf.h"
>
> +/*
> + * On Hyper-V, to reset, we need to read from this offset
> + * from the PCI config space. This is the mechanism used on
> + * Hyper-V to support PF/VF communication.
> + */
> +#define IXGBE_HV_RESET_OFFSET           0x201
> +
>  /**
>   *  ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
>   *  @hw: pointer to hardware structure
> @@ -126,6 +133,23 @@ static s32 ixgbevf_reset_hw_vf(struct ixgbe_hw *hw)
>  }
>
>  /**
> + * Hyper-V variant; the VF/PF communication is through the PCI
> + * config space.
> + */
> +static s32 ixgbevf_hv_reset_hw_vf(struct ixgbe_hw *hw)
> +{
> +       struct ixgbevf_adapter *adapter = hw->back;
> +       int i;
> +
> +       for (i = 0; i < 6; i++)
> +               pci_read_config_byte(adapter->pdev,
> +                                    (i + IXGBE_HV_RESET_OFFSET),
> +                                    &hw->mac.perm_addr[i]);
> +
> +       return 0;
> +}
> +

I'm still not seeing anything that protects the HyperV VF from being
built with MM_CONFIG disabled.  As such this driver will just fail
with no explanation in such a case.  If nothing else you could add
some code here that printed an error message if MM_CONFIG is disabled
at the very least.

> +/**
>   *  ixgbevf_stop_hw_vf - Generic stop Tx/Rx units
>   *  @hw: pointer to hardware structure
>   *
> @@ -258,6 +282,11 @@ static s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
>         return ret_val;
>  }
>
> +static s32 ixgbevf_hv_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
>  /**
>   * ixgbevf_get_reta_locked - get the RSS redirection table (RETA) contents.
>   * @adapter: pointer to the port handle
> @@ -416,6 +445,26 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
>         return ret_val;
>  }
>
> +/**
> + *  ixgbevf_hv_set_rar_vf - set device MAC address Hyper-V variant
> + *  @hw: pointer to hardware structure
> + *  @index: Receive address register to write
> + *  @addr: Address to put into receive address register
> + *  @vmdq: Unused in this implementation
> + *
> + * We don't really allow setting the device MAC address. However,
> + * if the address being set is the permanent MAC address we will
> + * permit that.
> + **/
> +static s32 ixgbevf_hv_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
> +                                u32 vmdq)
> +{
> +       if (ether_addr_equal(addr, hw->mac.perm_addr))
> +               return 0;
> +
> +       return -EOPNOTSUPP;
> +}
> +
>  static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,
>                                        u32 *msg, u16 size)
>  {
> @@ -473,6 +522,15 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
>  }
>
>  /**
> + * Hyper-V variant - just a stub.
> + */
> +static s32 ixgbevf_hv_update_mc_addr_list_vf(struct ixgbe_hw *hw,
> +                                         struct net_device *netdev)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
> +/**
>   *  ixgbevf_update_xcast_mode - Update Multicast mode
>   *  @hw: pointer to the HW structure
>   *  @netdev: pointer to net device structure
> @@ -513,6 +571,15 @@ static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw,
>  }
>
>  /**
> + * Hyper-V variant - just a stub.
> + */
> +static s32 ixgbevf_hv_update_xcast_mode(struct ixgbe_hw *hw,
> +                                       struct net_device *netdev, int xcast_mode)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
> +/**
>   *  ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address
>   *  @hw: pointer to the HW structure
>   *  @vlan: 12 bit VLAN ID
> @@ -551,6 +618,15 @@ mbx_err:
>  }
>
>  /**
> + * Hyper-V variant - just a stub.
> + */
> +static s32 ixgbevf_hv_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
> +                                 bool vlan_on)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
> +/**
>   *  ixgbevf_setup_mac_link_vf - Setup MAC link settings
>   *  @hw: pointer to hardware structure
>   *  @speed: Unused in this implementation
> @@ -656,6 +732,67 @@ out:
>  }
>
>  /**
> + * Hyper-V variant; there is no mailbox communication.
> + */
> +static s32 ixgbevf_hv_check_mac_link_vf(struct ixgbe_hw *hw,
> +                                       ixgbe_link_speed *speed,
> +                                       bool *link_up,
> +                                       bool autoneg_wait_to_complete)
> +{
> +       struct ixgbe_mbx_info *mbx = &hw->mbx;
> +       struct ixgbe_mac_info *mac = &hw->mac;
> +       u32 links_reg;
> +
> +       /* If we were hit with a reset drop the link */
> +       if (!mbx->ops.check_for_rst(hw) || !mbx->timeout)
> +               mac->get_link_status = true;
> +
> +       if (!mac->get_link_status)
> +               goto out;
> +
> +       /* if link status is down no point in checking to see if pf is up */
> +       links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
> +       if (!(links_reg & IXGBE_LINKS_UP))
> +               goto out;
> +
> +       /* for SFP+ modules and DA cables on 82599 it can take up to 500usecs
> +        * before the link status is correct
> +        */
> +       if (mac->type == ixgbe_mac_82599_vf) {
> +               int i;
> +
> +               for (i = 0; i < 5; i++) {
> +                       udelay(100);
> +                       links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
> +
> +                       if (!(links_reg & IXGBE_LINKS_UP))
> +                               goto out;
> +               }
> +       }
> +
> +       switch (links_reg & IXGBE_LINKS_SPEED_82599) {
> +       case IXGBE_LINKS_SPEED_10G_82599:
> +               *speed = IXGBE_LINK_SPEED_10GB_FULL;
> +               break;
> +       case IXGBE_LINKS_SPEED_1G_82599:
> +               *speed = IXGBE_LINK_SPEED_1GB_FULL;
> +               break;
> +       case IXGBE_LINKS_SPEED_100_82599:
> +               *speed = IXGBE_LINK_SPEED_100_FULL;
> +               break;
> +       }
> +
> +       /* if we passed all the tests above then the link is up and we no
> +        * longer need to check for link
> +        */
> +       mac->get_link_status = false;
> +
> +out:
> +       *link_up = !mac->get_link_status;
> +       return 0;
> +}
> +
> +/**
>   *  ixgbevf_rlpml_set_vf - Set the maximum receive packet length
>   *  @hw: pointer to the HW structure
>   *  @max_size: value to assign to max frame size
> @@ -663,6 +800,18 @@ out:
>  void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size)
>  {
>         u32 msgbuf[2];
> +       u32 reg;
> +
> +       if (ixgbevf_on_hyperv(hw)) {
> +               /* If we are on Hyper-V, we implement
> +                * this functionality differently.
> +                */
> +               reg =  IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(0));
> +               /* CRC == 4 */
> +               reg |= ((max_size + 4) | IXGBE_RXDCTL_RLPML_EN);
> +               IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(0), reg);
> +               return;
> +       }
>
>         msgbuf[0] = IXGBE_VF_SET_LPE;
>         msgbuf[1] = max_size;

There is no point in making this one function.  You should split this
code out and create a HyperV version of the function that you can call
instead.  It would help to make this more readable anyway since you
can then drop one level of indentation.

> @@ -679,6 +828,15 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
>         int err;
>         u32 msg[3];
>
> +       if (ixgbevf_on_hyperv(hw)) {
> +               /* Hyper-V only supports api version ixgbe_mbox_api_10
> +                */
> +               if (api != ixgbe_mbox_api_10)
> +                       return IXGBE_ERR_INVALID_ARGUMENT;
> +
> +               return 0;
> +       }
> +
>         /* Negotiate the mailbox API version */
>         msg[0] = IXGBE_VF_API_NEGOTIATE;
>         msg[1] = api;

Same thing here.  You can just create a new function and avoid having
to mess with the mailbox based approach.

> @@ -776,22 +934,65 @@ static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
>         .set_vfta               = ixgbevf_set_vfta_vf,
>  };
>
> +static const struct ixgbe_mac_operations ixgbevf_hv_mac_ops = {
> +       .init_hw                = ixgbevf_init_hw_vf,
> +       .reset_hw               = ixgbevf_hv_reset_hw_vf,
> +       .start_hw               = ixgbevf_start_hw_vf,
> +       .get_mac_addr           = ixgbevf_get_mac_addr_vf,
> +       .stop_adapter           = ixgbevf_stop_hw_vf,
> +       .setup_link             = ixgbevf_setup_mac_link_vf,
> +       .check_link             = ixgbevf_hv_check_mac_link_vf,
> +       .set_rar                = ixgbevf_hv_set_rar_vf,
> +       .update_mc_addr_list    = ixgbevf_hv_update_mc_addr_list_vf,
> +       .update_xcast_mode      = ixgbevf_hv_update_xcast_mode,
> +       .set_uc_addr            = ixgbevf_hv_set_uc_addr_vf,
> +       .set_vfta               = ixgbevf_hv_set_vfta_vf,
> +};
> +
>  const struct ixgbevf_info ixgbevf_82599_vf_info = {
>         .mac = ixgbe_mac_82599_vf,
>         .mac_ops = &ixgbevf_mac_ops,
>  };
>
> +const struct ixgbevf_info ixgbevf_82599_vf_hv_info = {
> +       .mac = ixgbe_mac_82599_vf,
> +       .mac_ops = &ixgbevf_hv_mac_ops,
> +};
> +
>  const struct ixgbevf_info ixgbevf_X540_vf_info = {
>         .mac = ixgbe_mac_X540_vf,
>         .mac_ops = &ixgbevf_mac_ops,
>  };
>
> +const struct ixgbevf_info ixgbevf_X540_vf_hv_info = {
> +       .mac = ixgbe_mac_X540_vf,
> +       .mac_ops = &ixgbevf_hv_mac_ops,
> +};
> +
>  const struct ixgbevf_info ixgbevf_X550_vf_info = {
>         .mac = ixgbe_mac_X550_vf,
>         .mac_ops = &ixgbevf_mac_ops,
>  };
>
> +const struct ixgbevf_info ixgbevf_X550_vf_hv_info = {
> +       .mac = ixgbe_mac_X550_vf,
> +       .mac_ops = &ixgbevf_hv_mac_ops,
> +};
> +
>  const struct ixgbevf_info ixgbevf_X550EM_x_vf_info = {
>         .mac = ixgbe_mac_X550EM_x_vf,
>         .mac_ops = &ixgbevf_mac_ops,
>  };
> +
> +const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info = {
> +       .mac = ixgbe_mac_X550EM_x_vf,
> +       .mac_ops = &ixgbevf_hv_mac_ops,
> +};
> +
> +bool ixgbevf_on_hyperv(struct ixgbe_hw *hw)
> +{
> +       if (hw->mbx.ops.check_for_msg == NULL)
> +               return true;
> +       else
> +               return false;
> +}
> --
> 1.7.4.1
>
> _______________________________________________
> Intel-wired-lan mailing list
> Intel-wired-lan@lists.osuosl.org
> http://lists.osuosl.org/mailman/listinfo/intel-wired-lan
KY Srinivasan April 18, 2016, 4:52 p.m. UTC | #2
> -----Original Message-----

> From: Alexander Duyck [mailto:alexander.duyck@gmail.com]

> Sent: Monday, April 18, 2016 9:18 AM

> To: KY Srinivasan <kys@microsoft.com>

> Cc: David Miller <davem@davemloft.net>; Netdev

> <netdev@vger.kernel.org>; linux-kernel@vger.kernel.org;

> devel@linuxdriverproject.org; olaf@aepfle.de; Robo Bot

> <apw@canonical.com>; Jason Wang <jasowang@redhat.com>;

> eli@mellanox.com; jackm@mellanox.com; yevgenyp@mellanox.com; John

> Ronciak <john.ronciak@intel.com>; intel-wired-lan <intel-wired-

> lan@lists.osuosl.org>

> Subject: Re: [Intel-wired-lan] [PATCH net-next V2 2/2] intel: ixgbevf: Support

> Windows hosts (Hyper-V)

> 

> On Sun, Apr 17, 2016 at 10:22 PM, K. Y. Srinivasan <kys@microsoft.com>

> wrote:

> > On Hyper-V, the VF/PF communication is a via software mediated path

> > as opposed to the hardware mailbox. Make the necessary

> > adjustments to support Hyper-V.

> >

> > Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>

> > ---

> >         V2: Addressed most of the comments from

> >             Alexander Duyck <alexander.duyck@gmail.com>

> >             and Rustad, Mark D <mark.d.rustad@intel.com>.

> >

> >  drivers/net/ethernet/intel/ixgbevf/ixgbevf.h      |   12 ++

> >  drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c |   16 ++-

> >  drivers/net/ethernet/intel/ixgbevf/mbx.c          |   12 ++

> >  drivers/net/ethernet/intel/ixgbevf/vf.c           |  201

> +++++++++++++++++++++

> >  4 files changed, 237 insertions(+), 4 deletions(-)

> >

> > diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h

> b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h

> > index 5ac60ee..3296d27 100644

> > --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h

> > +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h

> > @@ -460,9 +460,13 @@ enum ixbgevf_state_t {

> >

> >  enum ixgbevf_boards {

> >         board_82599_vf,

> > +       board_82599_vf_hv,

> >         board_X540_vf,

> > +       board_X540_vf_hv,

> >         board_X550_vf,

> > +       board_X550_vf_hv,

> >         board_X550EM_x_vf,

> > +       board_X550EM_x_vf_hv,

> >  };

> >

> >  enum ixgbevf_xcast_modes {

> > @@ -477,6 +481,13 @@ extern const struct ixgbevf_info

> ixgbevf_X550_vf_info;

> >  extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_info;

> >  extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;

> >

> > +

> > +extern const struct ixgbevf_info ixgbevf_82599_vf_hv_info;

> > +extern const struct ixgbevf_info ixgbevf_X540_vf_hv_info;

> > +extern const struct ixgbevf_info ixgbevf_X550_vf_hv_info;

> > +extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info;

> > +extern const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops;

> > +

> >  /* needed by ethtool.c */

> >  extern const char ixgbevf_driver_name[];

> >  extern const char ixgbevf_driver_version[];

> > @@ -494,6 +505,7 @@ void ixgbevf_free_rx_resources(struct ixgbevf_ring

> *);

> >  void ixgbevf_free_tx_resources(struct ixgbevf_ring *);

> >  void ixgbevf_update_stats(struct ixgbevf_adapter *adapter);

> >  int ethtool_ioctl(struct ifreq *ifr);

> > +bool ixgbevf_on_hyperv(struct ixgbe_hw *hw);

> >

> >  extern void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector);

> >

> > diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

> b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

> > index 007cbe0..c761d80 100644

> > --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

> > +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c

> > @@ -62,10 +62,14 @@ static char ixgbevf_copyright[] =

> >         "Copyright (c) 2009 - 2015 Intel Corporation.";

> >

> >  static const struct ixgbevf_info *ixgbevf_info_tbl[] = {

> > -       [board_82599_vf] = &ixgbevf_82599_vf_info,

> > -       [board_X540_vf]  = &ixgbevf_X540_vf_info,

> > -       [board_X550_vf]  = &ixgbevf_X550_vf_info,

> > -       [board_X550EM_x_vf] = &ixgbevf_X550EM_x_vf_info,

> > +       [board_82599_vf]        = &ixgbevf_82599_vf_info,

> > +       [board_82599_vf_hv]     = &ixgbevf_82599_vf_hv_info,

> > +       [board_X540_vf]         = &ixgbevf_X540_vf_info,

> > +       [board_X540_vf_hv]      = &ixgbevf_X540_vf_hv_info,

> > +       [board_X550_vf]         = &ixgbevf_X550_vf_info,

> > +       [board_X550_vf_hv]      = &ixgbevf_X550_vf_hv_info,

> > +       [board_X550EM_x_vf]     = &ixgbevf_X550EM_x_vf_info,

> > +       [board_X550EM_x_vf_hv]  = &ixgbevf_X550EM_x_vf_hv_info,

> >  };

> >

> >  /* ixgbevf_pci_tbl - PCI Device ID Table

> > @@ -78,9 +82,13 @@ static const struct ixgbevf_info *ixgbevf_info_tbl[] =

> {

> >   */

> >  static const struct pci_device_id ixgbevf_pci_tbl[] = {

> >         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf },

> > +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF_HV),

> board_82599_vf_hv },

> >         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf },

> > +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF_HV),

> board_X540_vf_hv },

> >         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF), board_X550_vf },

> > +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF_HV),

> board_X550_vf_hv },

> >         {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF),

> board_X550EM_x_vf },

> > +       {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV),

> board_X550EM_x_vf_hv},

> >         /* required last entry */

> >         {0, }

> >  };

> > diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c

> b/drivers/net/ethernet/intel/ixgbevf/mbx.c

> > index dc68fea..298a0da 100644

> > --- a/drivers/net/ethernet/intel/ixgbevf/mbx.c

> > +++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c

> > @@ -346,3 +346,15 @@ const struct ixgbe_mbx_operations

> ixgbevf_mbx_ops = {

> >         .check_for_rst  = ixgbevf_check_for_rst_vf,

> >  };

> >

> > +/**

> > + * Mailbox operations when running on Hyper-V.

> > + * On Hyper-V, PF/VF communiction is not through the

> > + * hardware mailbox; this communication is through

> > + * a software mediated path.

> > + * Most mail box operations are noop while running on

> > + * Hyper-V.

> > + */

> > +const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops = {

> > +       .init_params    = ixgbevf_init_mbx_params_vf,

> > +       .check_for_rst  = ixgbevf_check_for_rst_vf,

> > +};

> > diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c

> b/drivers/net/ethernet/intel/ixgbevf/vf.c

> > index 4d613a4..1ec13c1 100644

> > --- a/drivers/net/ethernet/intel/ixgbevf/vf.c

> > +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c

> > @@ -27,6 +27,13 @@

> >  #include "vf.h"

> >  #include "ixgbevf.h"

> >

> > +/*

> > + * On Hyper-V, to reset, we need to read from this offset

> > + * from the PCI config space. This is the mechanism used on

> > + * Hyper-V to support PF/VF communication.

> > + */

> > +#define IXGBE_HV_RESET_OFFSET           0x201

> > +

> >  /**

> >   *  ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx

> >   *  @hw: pointer to hardware structure

> > @@ -126,6 +133,23 @@ static s32 ixgbevf_reset_hw_vf(struct ixgbe_hw

> *hw)

> >  }

> >

> >  /**

> > + * Hyper-V variant; the VF/PF communication is through the PCI

> > + * config space.

> > + */

> > +static s32 ixgbevf_hv_reset_hw_vf(struct ixgbe_hw *hw)

> > +{

> > +       struct ixgbevf_adapter *adapter = hw->back;

> > +       int i;

> > +

> > +       for (i = 0; i < 6; i++)

> > +               pci_read_config_byte(adapter->pdev,

> > +                                    (i + IXGBE_HV_RESET_OFFSET),

> > +                                    &hw->mac.perm_addr[i]);

> > +

> > +       return 0;

> > +}

> > +

> 

> I'm still not seeing anything that protects the HyperV VF from being

> built with MM_CONFIG disabled.  As such this driver will just fail

> with no explanation in such a case.  If nothing else you could add

> some code here that printed an error message if MM_CONFIG is disabled

> at the very least.

I will add the error message.

> 

> > +/**

> >   *  ixgbevf_stop_hw_vf - Generic stop Tx/Rx units

> >   *  @hw: pointer to hardware structure

> >   *

> > @@ -258,6 +282,11 @@ static s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw

> *hw, u32 index, u8 *addr)

> >         return ret_val;

> >  }

> >

> > +static s32 ixgbevf_hv_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index,

> u8 *addr)

> > +{

> > +       return -EOPNOTSUPP;

> > +}

> > +

> >  /**

> >   * ixgbevf_get_reta_locked - get the RSS redirection table (RETA)

> contents.

> >   * @adapter: pointer to the port handle

> > @@ -416,6 +445,26 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw

> *hw, u32 index, u8 *addr,

> >         return ret_val;

> >  }

> >

> > +/**

> > + *  ixgbevf_hv_set_rar_vf - set device MAC address Hyper-V variant

> > + *  @hw: pointer to hardware structure

> > + *  @index: Receive address register to write

> > + *  @addr: Address to put into receive address register

> > + *  @vmdq: Unused in this implementation

> > + *

> > + * We don't really allow setting the device MAC address. However,

> > + * if the address being set is the permanent MAC address we will

> > + * permit that.

> > + **/

> > +static s32 ixgbevf_hv_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8

> *addr,

> > +                                u32 vmdq)

> > +{

> > +       if (ether_addr_equal(addr, hw->mac.perm_addr))

> > +               return 0;

> > +

> > +       return -EOPNOTSUPP;

> > +}

> > +

> >  static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,

> >                                        u32 *msg, u16 size)

> >  {

> > @@ -473,6 +522,15 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct

> ixgbe_hw *hw,

> >  }

> >

> >  /**

> > + * Hyper-V variant - just a stub.

> > + */

> > +static s32 ixgbevf_hv_update_mc_addr_list_vf(struct ixgbe_hw *hw,

> > +                                         struct net_device *netdev)

> > +{

> > +       return -EOPNOTSUPP;

> > +}

> > +

> > +/**

> >   *  ixgbevf_update_xcast_mode - Update Multicast mode

> >   *  @hw: pointer to the HW structure

> >   *  @netdev: pointer to net device structure

> > @@ -513,6 +571,15 @@ static s32 ixgbevf_update_xcast_mode(struct

> ixgbe_hw *hw,

> >  }

> >

> >  /**

> > + * Hyper-V variant - just a stub.

> > + */

> > +static s32 ixgbevf_hv_update_xcast_mode(struct ixgbe_hw *hw,

> > +                                       struct net_device *netdev, int xcast_mode)

> > +{

> > +       return -EOPNOTSUPP;

> > +}

> > +

> > +/**

> >   *  ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address

> >   *  @hw: pointer to the HW structure

> >   *  @vlan: 12 bit VLAN ID

> > @@ -551,6 +618,15 @@ mbx_err:

> >  }

> >

> >  /**

> > + * Hyper-V variant - just a stub.

> > + */

> > +static s32 ixgbevf_hv_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32

> vind,

> > +                                 bool vlan_on)

> > +{

> > +       return -EOPNOTSUPP;

> > +}

> > +

> > +/**

> >   *  ixgbevf_setup_mac_link_vf - Setup MAC link settings

> >   *  @hw: pointer to hardware structure

> >   *  @speed: Unused in this implementation

> > @@ -656,6 +732,67 @@ out:

> >  }

> >

> >  /**

> > + * Hyper-V variant; there is no mailbox communication.

> > + */

> > +static s32 ixgbevf_hv_check_mac_link_vf(struct ixgbe_hw *hw,

> > +                                       ixgbe_link_speed *speed,

> > +                                       bool *link_up,

> > +                                       bool autoneg_wait_to_complete)

> > +{

> > +       struct ixgbe_mbx_info *mbx = &hw->mbx;

> > +       struct ixgbe_mac_info *mac = &hw->mac;

> > +       u32 links_reg;

> > +

> > +       /* If we were hit with a reset drop the link */

> > +       if (!mbx->ops.check_for_rst(hw) || !mbx->timeout)

> > +               mac->get_link_status = true;

> > +

> > +       if (!mac->get_link_status)

> > +               goto out;

> > +

> > +       /* if link status is down no point in checking to see if pf is up */

> > +       links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);

> > +       if (!(links_reg & IXGBE_LINKS_UP))

> > +               goto out;

> > +

> > +       /* for SFP+ modules and DA cables on 82599 it can take up to 500usecs

> > +        * before the link status is correct

> > +        */

> > +       if (mac->type == ixgbe_mac_82599_vf) {

> > +               int i;

> > +

> > +               for (i = 0; i < 5; i++) {

> > +                       udelay(100);

> > +                       links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);

> > +

> > +                       if (!(links_reg & IXGBE_LINKS_UP))

> > +                               goto out;

> > +               }

> > +       }

> > +

> > +       switch (links_reg & IXGBE_LINKS_SPEED_82599) {

> > +       case IXGBE_LINKS_SPEED_10G_82599:

> > +               *speed = IXGBE_LINK_SPEED_10GB_FULL;

> > +               break;

> > +       case IXGBE_LINKS_SPEED_1G_82599:

> > +               *speed = IXGBE_LINK_SPEED_1GB_FULL;

> > +               break;

> > +       case IXGBE_LINKS_SPEED_100_82599:

> > +               *speed = IXGBE_LINK_SPEED_100_FULL;

> > +               break;

> > +       }

> > +

> > +       /* if we passed all the tests above then the link is up and we no

> > +        * longer need to check for link

> > +        */

> > +       mac->get_link_status = false;

> > +

> > +out:

> > +       *link_up = !mac->get_link_status;

> > +       return 0;

> > +}

> > +

> > +/**

> >   *  ixgbevf_rlpml_set_vf - Set the maximum receive packet length

> >   *  @hw: pointer to the HW structure

> >   *  @max_size: value to assign to max frame size

> > @@ -663,6 +800,18 @@ out:

> >  void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size)

> >  {

> >         u32 msgbuf[2];

> > +       u32 reg;

> > +

> > +       if (ixgbevf_on_hyperv(hw)) {

> > +               /* If we are on Hyper-V, we implement

> > +                * this functionality differently.

> > +                */

> > +               reg =  IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(0));

> > +               /* CRC == 4 */

> > +               reg |= ((max_size + 4) | IXGBE_RXDCTL_RLPML_EN);

> > +               IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(0), reg);

> > +               return;

> > +       }

> >

> >         msgbuf[0] = IXGBE_VF_SET_LPE;

> >         msgbuf[1] = max_size;

> 

> There is no point in making this one function.  You should split this

> code out and create a HyperV version of the function that you can call

> instead.  It would help to make this more readable anyway since you

> can then drop one level of indentation.


I will split the function as you have suggested.

> 

> > @@ -679,6 +828,15 @@ int ixgbevf_negotiate_api_version(struct

> ixgbe_hw *hw, int api)

> >         int err;

> >         u32 msg[3];

> >

> > +       if (ixgbevf_on_hyperv(hw)) {

> > +               /* Hyper-V only supports api version ixgbe_mbox_api_10

> > +                */

> > +               if (api != ixgbe_mbox_api_10)

> > +                       return IXGBE_ERR_INVALID_ARGUMENT;

> > +

> > +               return 0;

> > +       }

> > +

> >         /* Negotiate the mailbox API version */

> >         msg[0] = IXGBE_VF_API_NEGOTIATE;

> >         msg[1] = api;

> 

> Same thing here.  You can just create a new function and avoid having

> to mess with the mailbox based approach.


I will split the function as you have suggested.
> 

> > @@ -776,22 +934,65 @@ static const struct ixgbe_mac_operations

> ixgbevf_mac_ops = {

> >         .set_vfta               = ixgbevf_set_vfta_vf,

> >  };

> >

> > +static const struct ixgbe_mac_operations ixgbevf_hv_mac_ops = {

> > +       .init_hw                = ixgbevf_init_hw_vf,

> > +       .reset_hw               = ixgbevf_hv_reset_hw_vf,

> > +       .start_hw               = ixgbevf_start_hw_vf,

> > +       .get_mac_addr           = ixgbevf_get_mac_addr_vf,

> > +       .stop_adapter           = ixgbevf_stop_hw_vf,

> > +       .setup_link             = ixgbevf_setup_mac_link_vf,

> > +       .check_link             = ixgbevf_hv_check_mac_link_vf,

> > +       .set_rar                = ixgbevf_hv_set_rar_vf,

> > +       .update_mc_addr_list    = ixgbevf_hv_update_mc_addr_list_vf,

> > +       .update_xcast_mode      = ixgbevf_hv_update_xcast_mode,

> > +       .set_uc_addr            = ixgbevf_hv_set_uc_addr_vf,

> > +       .set_vfta               = ixgbevf_hv_set_vfta_vf,

> > +};

> > +

> >  const struct ixgbevf_info ixgbevf_82599_vf_info = {

> >         .mac = ixgbe_mac_82599_vf,

> >         .mac_ops = &ixgbevf_mac_ops,

> >  };

> >

> > +const struct ixgbevf_info ixgbevf_82599_vf_hv_info = {

> > +       .mac = ixgbe_mac_82599_vf,

> > +       .mac_ops = &ixgbevf_hv_mac_ops,

> > +};

> > +

> >  const struct ixgbevf_info ixgbevf_X540_vf_info = {

> >         .mac = ixgbe_mac_X540_vf,

> >         .mac_ops = &ixgbevf_mac_ops,

> >  };

> >

> > +const struct ixgbevf_info ixgbevf_X540_vf_hv_info = {

> > +       .mac = ixgbe_mac_X540_vf,

> > +       .mac_ops = &ixgbevf_hv_mac_ops,

> > +};

> > +

> >  const struct ixgbevf_info ixgbevf_X550_vf_info = {

> >         .mac = ixgbe_mac_X550_vf,

> >         .mac_ops = &ixgbevf_mac_ops,

> >  };

> >

> > +const struct ixgbevf_info ixgbevf_X550_vf_hv_info = {

> > +       .mac = ixgbe_mac_X550_vf,

> > +       .mac_ops = &ixgbevf_hv_mac_ops,

> > +};

> > +

> >  const struct ixgbevf_info ixgbevf_X550EM_x_vf_info = {

> >         .mac = ixgbe_mac_X550EM_x_vf,

> >         .mac_ops = &ixgbevf_mac_ops,

> >  };

> > +

> > +const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info = {

> > +       .mac = ixgbe_mac_X550EM_x_vf,

> > +       .mac_ops = &ixgbevf_hv_mac_ops,

> > +};

> > +

> > +bool ixgbevf_on_hyperv(struct ixgbe_hw *hw)

> > +{

> > +       if (hw->mbx.ops.check_for_msg == NULL)

> > +               return true;

> > +       else

> > +               return false;

> > +}

> > --

> > 1.7.4.1


Thank you.

K. Y
> >

> > _______________________________________________

> > Intel-wired-lan mailing list

> > Intel-wired-lan@lists.osuosl.org

> >

> https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2flists.osu

> osl.org%2fmailman%2flistinfo%2fintel-wired-

> lan&data=01%7c01%7ckys%40microsoft.com%7cfdaf85b858e240c2e38108d3

> 67a4f2d7%7c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=Vf%2fXiRxqiEa

> OaUMQNN9kM1A12IV5JCkEXVILgAEFbYI%3d
Joe Perches April 18, 2016, 5 p.m. UTC | #3
On Mon, 2016-04-18 at 16:52 +0000, KY Srinivasan wrote:
[]
> > > +bool ixgbevf_on_hyperv(struct ixgbe_hw *hw)
> > > +{
> > > +       if (hw->mbx.ops.check_for_msg == NULL)
> > > +               return true;
> > > +       else
> > > +               return false;
> > > +}

trivia:

bool func(...)
{
	if (<bar>)
		return true;
	else
		return false;
}

can generally be written as:

bool func(...)
{
	return <bar>;
}
KY Srinivasan April 18, 2016, 7:42 p.m. UTC | #4
> -----Original Message-----
> From: Joe Perches [mailto:joe@perches.com]
> Sent: Monday, April 18, 2016 10:00 AM
> To: KY Srinivasan <kys@microsoft.com>; Alexander Duyck
> <alexander.duyck@gmail.com>
> Cc: David Miller <davem@davemloft.net>; Netdev
> <netdev@vger.kernel.org>; linux-kernel@vger.kernel.org;
> devel@linuxdriverproject.org; olaf@aepfle.de; Robo Bot
> <apw@canonical.com>; Jason Wang <jasowang@redhat.com>;
> eli@mellanox.com; jackm@mellanox.com; yevgenyp@mellanox.com; John
> Ronciak <john.ronciak@intel.com>; intel-wired-lan <intel-wired-
> lan@lists.osuosl.org>
> Subject: Re: [Intel-wired-lan] [PATCH net-next V2 2/2] intel: ixgbevf: Support
> Windows hosts (Hyper-V)
> 
> On Mon, 2016-04-18 at 16:52 +0000, KY Srinivasan wrote:
> []
> > > > +bool ixgbevf_on_hyperv(struct ixgbe_hw *hw)
> > > > +{
> > > > +       if (hw->mbx.ops.check_for_msg == NULL)
> > > > +               return true;
> > > > +       else
> > > > +               return false;
> > > > +}
> 
> trivia:
> 
> bool func(...)
> {
> 	if (<bar>)
> 		return true;
> 	else
> 		return false;
> }
> 
> can generally be written as:
> 
> bool func(...)
> {
> 	return <bar>;
> }

Thanks Joe; will update.

K. Y
diff mbox

Patch

diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 5ac60ee..3296d27 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -460,9 +460,13 @@  enum ixbgevf_state_t {
 
 enum ixgbevf_boards {
 	board_82599_vf,
+	board_82599_vf_hv,
 	board_X540_vf,
+	board_X540_vf_hv,
 	board_X550_vf,
+	board_X550_vf_hv,
 	board_X550EM_x_vf,
+	board_X550EM_x_vf_hv,
 };
 
 enum ixgbevf_xcast_modes {
@@ -477,6 +481,13 @@  extern const struct ixgbevf_info ixgbevf_X550_vf_info;
 extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_info;
 extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
 
+
+extern const struct ixgbevf_info ixgbevf_82599_vf_hv_info;
+extern const struct ixgbevf_info ixgbevf_X540_vf_hv_info;
+extern const struct ixgbevf_info ixgbevf_X550_vf_hv_info;
+extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info;
+extern const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops;
+
 /* needed by ethtool.c */
 extern const char ixgbevf_driver_name[];
 extern const char ixgbevf_driver_version[];
@@ -494,6 +505,7 @@  void ixgbevf_free_rx_resources(struct ixgbevf_ring *);
 void ixgbevf_free_tx_resources(struct ixgbevf_ring *);
 void ixgbevf_update_stats(struct ixgbevf_adapter *adapter);
 int ethtool_ioctl(struct ifreq *ifr);
+bool ixgbevf_on_hyperv(struct ixgbe_hw *hw);
 
 extern void ixgbevf_write_eitr(struct ixgbevf_q_vector *q_vector);
 
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 007cbe0..c761d80 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -62,10 +62,14 @@  static char ixgbevf_copyright[] =
 	"Copyright (c) 2009 - 2015 Intel Corporation.";
 
 static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
-	[board_82599_vf] = &ixgbevf_82599_vf_info,
-	[board_X540_vf]  = &ixgbevf_X540_vf_info,
-	[board_X550_vf]  = &ixgbevf_X550_vf_info,
-	[board_X550EM_x_vf] = &ixgbevf_X550EM_x_vf_info,
+	[board_82599_vf]	= &ixgbevf_82599_vf_info,
+	[board_82599_vf_hv]	= &ixgbevf_82599_vf_hv_info,
+	[board_X540_vf]		= &ixgbevf_X540_vf_info,
+	[board_X540_vf_hv]	= &ixgbevf_X540_vf_hv_info,
+	[board_X550_vf]		= &ixgbevf_X550_vf_info,
+	[board_X550_vf_hv]	= &ixgbevf_X550_vf_hv_info,
+	[board_X550EM_x_vf]	= &ixgbevf_X550EM_x_vf_info,
+	[board_X550EM_x_vf_hv]	= &ixgbevf_X550EM_x_vf_hv_info,
 };
 
 /* ixgbevf_pci_tbl - PCI Device ID Table
@@ -78,9 +82,13 @@  static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
  */
 static const struct pci_device_id ixgbevf_pci_tbl[] = {
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF), board_82599_vf },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_VF_HV), board_82599_vf_hv },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF), board_X540_vf },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540_VF_HV), board_X540_vf_hv },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF), board_X550_vf },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550_VF_HV), board_X550_vf_hv },
 	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF), board_X550EM_x_vf },
+	{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV), board_X550EM_x_vf_hv},
 	/* required last entry */
 	{0, }
 };
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
index dc68fea..298a0da 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.c
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
@@ -346,3 +346,15 @@  const struct ixgbe_mbx_operations ixgbevf_mbx_ops = {
 	.check_for_rst	= ixgbevf_check_for_rst_vf,
 };
 
+/**
+ * Mailbox operations when running on Hyper-V.
+ * On Hyper-V, PF/VF communiction is not through the
+ * hardware mailbox; this communication is through
+ * a software mediated path.
+ * Most mail box operations are noop while running on
+ * Hyper-V.
+ */
+const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops = {
+	.init_params	= ixgbevf_init_mbx_params_vf,
+	.check_for_rst	= ixgbevf_check_for_rst_vf,
+};
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 4d613a4..1ec13c1 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -27,6 +27,13 @@ 
 #include "vf.h"
 #include "ixgbevf.h"
 
+/*
+ * On Hyper-V, to reset, we need to read from this offset
+ * from the PCI config space. This is the mechanism used on
+ * Hyper-V to support PF/VF communication.
+ */
+#define IXGBE_HV_RESET_OFFSET           0x201
+
 /**
  *  ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
  *  @hw: pointer to hardware structure
@@ -126,6 +133,23 @@  static s32 ixgbevf_reset_hw_vf(struct ixgbe_hw *hw)
 }
 
 /**
+ * Hyper-V variant; the VF/PF communication is through the PCI
+ * config space.
+ */
+static s32 ixgbevf_hv_reset_hw_vf(struct ixgbe_hw *hw)
+{
+	struct ixgbevf_adapter *adapter = hw->back;
+	int i;
+
+	for (i = 0; i < 6; i++)
+		pci_read_config_byte(adapter->pdev,
+				     (i + IXGBE_HV_RESET_OFFSET),
+				     &hw->mac.perm_addr[i]);
+
+	return 0;
+}
+
+/**
  *  ixgbevf_stop_hw_vf - Generic stop Tx/Rx units
  *  @hw: pointer to hardware structure
  *
@@ -258,6 +282,11 @@  static s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
 	return ret_val;
 }
 
+static s32 ixgbevf_hv_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
+{
+	return -EOPNOTSUPP;
+}
+
 /**
  * ixgbevf_get_reta_locked - get the RSS redirection table (RETA) contents.
  * @adapter: pointer to the port handle
@@ -416,6 +445,26 @@  static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
 	return ret_val;
 }
 
+/**
+ *  ixgbevf_hv_set_rar_vf - set device MAC address Hyper-V variant
+ *  @hw: pointer to hardware structure
+ *  @index: Receive address register to write
+ *  @addr: Address to put into receive address register
+ *  @vmdq: Unused in this implementation
+ *
+ * We don't really allow setting the device MAC address. However,
+ * if the address being set is the permanent MAC address we will
+ * permit that.
+ **/
+static s32 ixgbevf_hv_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
+				 u32 vmdq)
+{
+	if (ether_addr_equal(addr, hw->mac.perm_addr))
+		return 0;
+
+	return -EOPNOTSUPP;
+}
+
 static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,
 				       u32 *msg, u16 size)
 {
@@ -473,6 +522,15 @@  static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
 }
 
 /**
+ * Hyper-V variant - just a stub.
+ */
+static s32 ixgbevf_hv_update_mc_addr_list_vf(struct ixgbe_hw *hw,
+					  struct net_device *netdev)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
  *  ixgbevf_update_xcast_mode - Update Multicast mode
  *  @hw: pointer to the HW structure
  *  @netdev: pointer to net device structure
@@ -513,6 +571,15 @@  static s32 ixgbevf_update_xcast_mode(struct ixgbe_hw *hw,
 }
 
 /**
+ * Hyper-V variant - just a stub.
+ */
+static s32 ixgbevf_hv_update_xcast_mode(struct ixgbe_hw *hw,
+					struct net_device *netdev, int xcast_mode)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
  *  ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address
  *  @hw: pointer to the HW structure
  *  @vlan: 12 bit VLAN ID
@@ -551,6 +618,15 @@  mbx_err:
 }
 
 /**
+ * Hyper-V variant - just a stub.
+ */
+static s32 ixgbevf_hv_set_vfta_vf(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+				  bool vlan_on)
+{
+	return -EOPNOTSUPP;
+}
+
+/**
  *  ixgbevf_setup_mac_link_vf - Setup MAC link settings
  *  @hw: pointer to hardware structure
  *  @speed: Unused in this implementation
@@ -656,6 +732,67 @@  out:
 }
 
 /**
+ * Hyper-V variant; there is no mailbox communication.
+ */
+static s32 ixgbevf_hv_check_mac_link_vf(struct ixgbe_hw *hw,
+					ixgbe_link_speed *speed,
+					bool *link_up,
+					bool autoneg_wait_to_complete)
+{
+	struct ixgbe_mbx_info *mbx = &hw->mbx;
+	struct ixgbe_mac_info *mac = &hw->mac;
+	u32 links_reg;
+
+	/* If we were hit with a reset drop the link */
+	if (!mbx->ops.check_for_rst(hw) || !mbx->timeout)
+		mac->get_link_status = true;
+
+	if (!mac->get_link_status)
+		goto out;
+
+	/* if link status is down no point in checking to see if pf is up */
+	links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
+	if (!(links_reg & IXGBE_LINKS_UP))
+		goto out;
+
+	/* for SFP+ modules and DA cables on 82599 it can take up to 500usecs
+	 * before the link status is correct
+	 */
+	if (mac->type == ixgbe_mac_82599_vf) {
+		int i;
+
+		for (i = 0; i < 5; i++) {
+			udelay(100);
+			links_reg = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
+
+			if (!(links_reg & IXGBE_LINKS_UP))
+				goto out;
+		}
+	}
+
+	switch (links_reg & IXGBE_LINKS_SPEED_82599) {
+	case IXGBE_LINKS_SPEED_10G_82599:
+		*speed = IXGBE_LINK_SPEED_10GB_FULL;
+		break;
+	case IXGBE_LINKS_SPEED_1G_82599:
+		*speed = IXGBE_LINK_SPEED_1GB_FULL;
+		break;
+	case IXGBE_LINKS_SPEED_100_82599:
+		*speed = IXGBE_LINK_SPEED_100_FULL;
+		break;
+	}
+
+	/* if we passed all the tests above then the link is up and we no
+	 * longer need to check for link
+	 */
+	mac->get_link_status = false;
+
+out:
+	*link_up = !mac->get_link_status;
+	return 0;
+}
+
+/**
  *  ixgbevf_rlpml_set_vf - Set the maximum receive packet length
  *  @hw: pointer to the HW structure
  *  @max_size: value to assign to max frame size
@@ -663,6 +800,18 @@  out:
 void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size)
 {
 	u32 msgbuf[2];
+	u32 reg;
+
+	if (ixgbevf_on_hyperv(hw)) {
+		/* If we are on Hyper-V, we implement
+		 * this functionality differently.
+		 */
+		reg =  IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(0));
+		/* CRC == 4 */
+		reg |= ((max_size + 4) | IXGBE_RXDCTL_RLPML_EN);
+		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(0), reg);
+		return;
+	}
 
 	msgbuf[0] = IXGBE_VF_SET_LPE;
 	msgbuf[1] = max_size;
@@ -679,6 +828,15 @@  int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
 	int err;
 	u32 msg[3];
 
+	if (ixgbevf_on_hyperv(hw)) {
+		/* Hyper-V only supports api version ixgbe_mbox_api_10
+		 */
+		if (api != ixgbe_mbox_api_10)
+			return IXGBE_ERR_INVALID_ARGUMENT;
+
+		return 0;
+	}
+
 	/* Negotiate the mailbox API version */
 	msg[0] = IXGBE_VF_API_NEGOTIATE;
 	msg[1] = api;
@@ -776,22 +934,65 @@  static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
 	.set_vfta		= ixgbevf_set_vfta_vf,
 };
 
+static const struct ixgbe_mac_operations ixgbevf_hv_mac_ops = {
+	.init_hw		= ixgbevf_init_hw_vf,
+	.reset_hw		= ixgbevf_hv_reset_hw_vf,
+	.start_hw		= ixgbevf_start_hw_vf,
+	.get_mac_addr		= ixgbevf_get_mac_addr_vf,
+	.stop_adapter		= ixgbevf_stop_hw_vf,
+	.setup_link		= ixgbevf_setup_mac_link_vf,
+	.check_link		= ixgbevf_hv_check_mac_link_vf,
+	.set_rar		= ixgbevf_hv_set_rar_vf,
+	.update_mc_addr_list	= ixgbevf_hv_update_mc_addr_list_vf,
+	.update_xcast_mode	= ixgbevf_hv_update_xcast_mode,
+	.set_uc_addr		= ixgbevf_hv_set_uc_addr_vf,
+	.set_vfta		= ixgbevf_hv_set_vfta_vf,
+};
+
 const struct ixgbevf_info ixgbevf_82599_vf_info = {
 	.mac = ixgbe_mac_82599_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
 
+const struct ixgbevf_info ixgbevf_82599_vf_hv_info = {
+	.mac = ixgbe_mac_82599_vf,
+	.mac_ops = &ixgbevf_hv_mac_ops,
+};
+
 const struct ixgbevf_info ixgbevf_X540_vf_info = {
 	.mac = ixgbe_mac_X540_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
 
+const struct ixgbevf_info ixgbevf_X540_vf_hv_info = {
+	.mac = ixgbe_mac_X540_vf,
+	.mac_ops = &ixgbevf_hv_mac_ops,
+};
+
 const struct ixgbevf_info ixgbevf_X550_vf_info = {
 	.mac = ixgbe_mac_X550_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
 
+const struct ixgbevf_info ixgbevf_X550_vf_hv_info = {
+	.mac = ixgbe_mac_X550_vf,
+	.mac_ops = &ixgbevf_hv_mac_ops,
+};
+
 const struct ixgbevf_info ixgbevf_X550EM_x_vf_info = {
 	.mac = ixgbe_mac_X550EM_x_vf,
 	.mac_ops = &ixgbevf_mac_ops,
 };
+
+const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info = {
+	.mac = ixgbe_mac_X550EM_x_vf,
+	.mac_ops = &ixgbevf_hv_mac_ops,
+};
+
+bool ixgbevf_on_hyperv(struct ixgbe_hw *hw)
+{
+	if (hw->mbx.ops.check_for_msg == NULL)
+		return true;
+	else
+		return false;
+}