ixgbevf: Add range checking for setting MTU
authorTony Nguyen <anthony.l.nguyen@intel.com>
Wed, 13 Jul 2016 17:33:16 +0000 (10:33 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 22 Jul 2016 08:52:08 +0000 (01:52 -0700)
Currently when setting the VF's MTU, the PF can return a NACK but this
isn't passed on to the VF.  Propagate the results from the PF to the VF
so errors can be reported.

In ixgbevf_change_mtu, return an error and reject the change.

For ixgbevf_configure_rx, log the error for debugging purposes since
the function is buried in a series of Rx config routines that are void.

Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/intel/ixgbevf/vf.c
drivers/net/ethernet/intel/ixgbevf/vf.h

index 201e48215c012ac1f347b9d5803b53230e699f0d..d9d6616f02a4d97a214204344f3be8704d887f67 100644 (file)
@@ -1802,16 +1802,19 @@ static void ixgbevf_configure_rx_ring(struct ixgbevf_adapter *adapter,
  **/
 static void ixgbevf_configure_rx(struct ixgbevf_adapter *adapter)
 {
-       int i;
        struct ixgbe_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
+       int i, ret;
 
        ixgbevf_setup_psrtype(adapter);
        if (hw->mac.type >= ixgbe_mac_X550_vf)
                ixgbevf_setup_vfmrqc(adapter);
 
        /* notify the PF of our intent to use this size of frame */
-       hw->mac.ops.set_rlpml(hw, netdev->mtu + ETH_HLEN + ETH_FCS_LEN);
+       ret = hw->mac.ops.set_rlpml(hw, netdev->mtu + ETH_HLEN + ETH_FCS_LEN);
+       if (ret)
+               dev_err(&adapter->pdev->dev,
+                       "Failed to set MTU at %d\n", netdev->mtu);
 
        /* Setup the HW Rx Head and Tail Descriptor Pointers and
         * the Base and Length of the Rx Descriptor Ring
@@ -3737,6 +3740,7 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
        struct ixgbe_hw *hw = &adapter->hw;
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
        int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
+       int ret;
 
        switch (adapter->hw.api_version) {
        case ixgbe_mbox_api_11:
@@ -3753,14 +3757,17 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
        if ((new_mtu < 68) || (max_frame > max_possible_frame))
                return -EINVAL;
 
+       /* notify the PF of our intent to use this size of frame */
+       ret = hw->mac.ops.set_rlpml(hw, max_frame);
+       if (ret)
+               return -EINVAL;
+
        hw_dbg(hw, "changing MTU from %d to %d\n",
               netdev->mtu, new_mtu);
+
        /* must set new MTU before calling down or up */
        netdev->mtu = new_mtu;
 
-       /* notify the PF of our intent to use this size of frame */
-       hw->mac.ops.set_rlpml(hw, max_frame);
-
        return 0;
 }
 
index cb409b3a31fff4719bb496806d7966869ad92796..4862bc2fa968faa171d080c6b27e1cedaf8c0c0f 100644 (file)
  */
 #define IXGBE_HV_RESET_OFFSET           0x201
 
+static inline s32 ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw, u32 *msg,
+                                            u32 *retmsg, u16 size)
+{
+       struct ixgbe_mbx_info *mbx = &hw->mbx;
+       s32 retval = mbx->ops.write_posted(hw, msg, size);
+
+       if (retval)
+               return retval;
+
+       return mbx->ops.read_posted(hw, retmsg, size);
+}
+
 /**
  *  ixgbevf_start_hw_vf - Prepare hardware for Tx/Rx
  *  @hw: pointer to hardware structure
@@ -470,17 +482,6 @@ static s32 ixgbevf_hv_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr,
        return -EOPNOTSUPP;
 }
 
-static void ixgbevf_write_msg_read_ack(struct ixgbe_hw *hw,
-                                      u32 *msg, u16 size)
-{
-       struct ixgbe_mbx_info *mbx = &hw->mbx;
-       u32 retmsg[IXGBE_VFMAILBOX_SIZE];
-       s32 retval = mbx->ops.write_posted(hw, msg, size);
-
-       if (!retval)
-               mbx->ops.read_posted(hw, retmsg, size);
-}
-
 /**
  *  ixgbevf_update_mc_addr_list_vf - Update Multicast addresses
  *  @hw: pointer to the HW structure
@@ -521,7 +522,7 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
                vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
        }
 
-       ixgbevf_write_msg_read_ack(hw, msgbuf, IXGBE_VFMAILBOX_SIZE);
+       ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, IXGBE_VFMAILBOX_SIZE);
 
        return 0;
 }
@@ -799,13 +800,22 @@ out:
  *  @hw: pointer to the HW structure
  *  @max_size: value to assign to max frame size
  **/
-static void ixgbevf_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size)
+static s32 ixgbevf_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size)
 {
        u32 msgbuf[2];
+       s32 ret_val;
 
        msgbuf[0] = IXGBE_VF_SET_LPE;
        msgbuf[1] = max_size;
-       ixgbevf_write_msg_read_ack(hw, msgbuf, 2);
+
+       ret_val = ixgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 2);
+       if (ret_val)
+               return ret_val;
+       if ((msgbuf[0] & IXGBE_VF_SET_LPE) &&
+           (msgbuf[0] & IXGBE_VT_MSGTYPE_NACK))
+               return IXGBE_ERR_MBX;
+
+       return 0;
 }
 
 /**
@@ -814,7 +824,7 @@ static void ixgbevf_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size)
  * @max_size: value to assign to max frame size
  * Hyper-V variant.
  **/
-static void ixgbevf_hv_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size)
+static s32 ixgbevf_hv_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size)
 {
        u32 reg;
 
@@ -825,6 +835,8 @@ static void ixgbevf_hv_set_rlpml_vf(struct ixgbe_hw *hw, u16 max_size)
        /* CRC == 4 */
        reg |= ((max_size + 4) | IXGBE_RXDCTL_RLPML_EN);
        IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(0), reg);
+
+       return 0;
 }
 
 /**
index e3a0dea3d6596506478ed35c88f52808051c83c3..04d8d4ee4f045e9fb929882c06f3bb5803981921 100644 (file)
@@ -69,7 +69,7 @@ struct ixgbe_mac_operations {
        s32 (*disable_mc)(struct ixgbe_hw *);
        s32 (*clear_vfta)(struct ixgbe_hw *);
        s32 (*set_vfta)(struct ixgbe_hw *, u32, u32, bool);
-       void (*set_rlpml)(struct ixgbe_hw *, u16);
+       s32 (*set_rlpml)(struct ixgbe_hw *, u16);
 };
 
 enum ixgbe_mac_type {