ixgbevf: Add macvlan support in the set rx mode op
authorGreg Rose <gregory.v.rose@intel.com>
Fri, 13 May 2011 01:33:42 +0000 (01:33 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Sun, 15 May 2011 00:50:44 +0000 (17:50 -0700)
Implement setup of unicast address list in the VF driver's set_rx_mode
netdev op.  Unicast addresses are sent to the PF via a mailbox message
and the PF will check if it has room in the RAR table and if so set the
filter for the VF.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Tested-by: Sibai Li <sibai.li@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ixgbevf/ixgbevf_main.c
drivers/net/ixgbevf/mbx.h
drivers/net/ixgbevf/vf.c
drivers/net/ixgbevf/vf.h

index 05fa7c85deed3351ec9c6ad8069f40c7ceae858b..d7ab202fb95c084baa785074a11f7e64c2777889 100644 (file)
@@ -1460,6 +1460,34 @@ static void ixgbevf_restore_vlan(struct ixgbevf_adapter *adapter)
        }
 }
 
+static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
+{
+       struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+       struct ixgbe_hw *hw = &adapter->hw;
+       int count = 0;
+
+       if ((netdev_uc_count(netdev)) > 10) {
+               printk(KERN_ERR "Too many unicast filters - No Space\n");
+               return -ENOSPC;
+       }
+
+       if (!netdev_uc_empty(netdev)) {
+               struct netdev_hw_addr *ha;
+               netdev_for_each_uc_addr(ha, netdev) {
+                       hw->mac.ops.set_uc_addr(hw, ++count, ha->addr);
+                       udelay(200);
+               }
+       } else {
+               /*
+                * If the list is empty then send message to PF driver to
+                * clear all macvlans on this VF.
+                */
+               hw->mac.ops.set_uc_addr(hw, 0, NULL);
+       }
+
+       return count;
+}
+
 /**
  * ixgbevf_set_rx_mode - Multicast set
  * @netdev: network interface device structure
@@ -1476,6 +1504,8 @@ static void ixgbevf_set_rx_mode(struct net_device *netdev)
        /* reprogram multicast list */
        if (hw->mac.ops.update_mc_addr_list)
                hw->mac.ops.update_mc_addr_list(hw, netdev);
+
+       ixgbevf_write_uc_addr_list(netdev);
 }
 
 static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter)
index b2b5bf5daa3d202cc74d8961ca5af9f411604bc1..ea393eb03f3aeba86c4658b0451a54b447e26034 100644 (file)
@@ -81,6 +81,7 @@
 #define IXGBE_VF_SET_MULTICAST    0x03 /* VF requests PF to set MC addr */
 #define IXGBE_VF_SET_VLAN         0x04 /* VF requests PF to set VLAN */
 #define IXGBE_VF_SET_LPE          0x05 /* VF requests PF to set VMOLR.LPE */
+#define IXGBE_VF_SET_MACVLAN      0x06 /* VF requests PF for unicast filter */
 
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
index eecd3bf6833f4c6ecd75c110cbcced7ffc2825fc..aa3682e8c473cc84bcf9c6bc0b7d17a12857854d 100644 (file)
@@ -216,6 +216,39 @@ static s32 ixgbevf_get_mac_addr_vf(struct ixgbe_hw *hw, u8 *mac_addr)
        return 0;
 }
 
+static s32 ixgbevf_set_uc_addr_vf(struct ixgbe_hw *hw, u32 index, u8 *addr)
+{
+       struct ixgbe_mbx_info *mbx = &hw->mbx;
+       u32 msgbuf[3];
+       u8 *msg_addr = (u8 *)(&msgbuf[1]);
+       s32 ret_val;
+
+       memset(msgbuf, 0, sizeof(msgbuf));
+       /*
+        * If index is one then this is the start of a new list and needs
+        * indication to the PF so it can do it's own list management.
+        * If it is zero then that tells the PF to just clear all of
+        * this VF's macvlans and there is no new list.
+        */
+       msgbuf[0] |= index << IXGBE_VT_MSGINFO_SHIFT;
+       msgbuf[0] |= IXGBE_VF_SET_MACVLAN;
+       if (addr)
+               memcpy(msg_addr, addr, 6);
+       ret_val = mbx->ops.write_posted(hw, msgbuf, 3);
+
+       if (!ret_val)
+               ret_val = mbx->ops.read_posted(hw, msgbuf, 3);
+
+       msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+
+       if (!ret_val)
+               if (msgbuf[0] ==
+                   (IXGBE_VF_SET_MACVLAN | IXGBE_VT_MSGTYPE_NACK))
+                       ret_val = -ENOMEM;
+
+       return ret_val;
+}
+
 /**
  *  ixgbevf_set_rar_vf - set device MAC address
  *  @hw: pointer to hardware structure
@@ -378,6 +411,7 @@ static struct ixgbe_mac_operations ixgbevf_mac_ops = {
        .check_link          = ixgbevf_check_mac_link_vf,
        .set_rar             = ixgbevf_set_rar_vf,
        .update_mc_addr_list = ixgbevf_update_mc_addr_list_vf,
+       .set_uc_addr         = ixgbevf_set_uc_addr_vf,
        .set_vfta            = ixgbevf_set_vfta_vf,
 };
 
index 23eb114c149fd21b3f41d200894976ddd9d5ff1f..10306b492ee61b5b9e686503839281b35b9df1fb 100644 (file)
@@ -62,6 +62,7 @@ struct ixgbe_mac_operations {
 
        /* RAR, Multicast, VLAN */
        s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32);
+       s32 (*set_uc_addr)(struct ixgbe_hw *, u32, u8 *);
        s32 (*init_rx_addrs)(struct ixgbe_hw *);
        s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *);
        s32 (*enable_mc)(struct ixgbe_hw *);