|
@@ -126,13 +126,34 @@ void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
|
|
|
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
|
|
|
}
|
|
|
|
|
|
+static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf)
|
|
|
+{
|
|
|
+ struct ixgbe_hw *hw = &adapter->hw;
|
|
|
+
|
|
|
+ if (vid)
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf),
|
|
|
+ (vid | IXGBE_VMVIR_VLANA_DEFAULT));
|
|
|
+ else
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
|
|
|
+}
|
|
|
+
|
|
|
inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
|
|
|
{
|
|
|
struct ixgbe_hw *hw = &adapter->hw;
|
|
|
|
|
|
/* reset offloads to defaults */
|
|
|
- ixgbe_set_vmolr(hw, vf, true);
|
|
|
-
|
|
|
+ if (adapter->vfinfo[vf].pf_vlan) {
|
|
|
+ ixgbe_set_vf_vlan(adapter, true,
|
|
|
+ adapter->vfinfo[vf].pf_vlan, vf);
|
|
|
+ ixgbe_set_vmvir(adapter,
|
|
|
+ (adapter->vfinfo[vf].pf_vlan |
|
|
|
+ (adapter->vfinfo[vf].pf_qos <<
|
|
|
+ VLAN_PRIO_SHIFT)), vf);
|
|
|
+ ixgbe_set_vmolr(hw, vf, false);
|
|
|
+ } else {
|
|
|
+ ixgbe_set_vmvir(adapter, 0, vf);
|
|
|
+ ixgbe_set_vmolr(hw, vf, true);
|
|
|
+ }
|
|
|
|
|
|
/* reset multicast table array for vf */
|
|
|
adapter->vfinfo[vf].num_vf_mc_hashes = 0;
|
|
@@ -266,10 +287,12 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
|
|
|
case IXGBE_VF_SET_MAC_ADDR:
|
|
|
{
|
|
|
u8 *new_mac = ((u8 *)(&msgbuf[1]));
|
|
|
- if (is_valid_ether_addr(new_mac))
|
|
|
+ if (is_valid_ether_addr(new_mac) &&
|
|
|
+ !adapter->vfinfo[vf].pf_set_mac)
|
|
|
ixgbe_set_vf_mac(adapter, vf, new_mac);
|
|
|
else
|
|
|
- retval = -1;
|
|
|
+ ixgbe_set_vf_mac(adapter,
|
|
|
+ vf, adapter->vfinfo[vf].vf_mac_addresses);
|
|
|
}
|
|
|
break;
|
|
|
case IXGBE_VF_SET_MULTICAST:
|
|
@@ -363,3 +386,76 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
|
|
|
+{
|
|
|
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
|
|
+ if (!is_valid_ether_addr(mac) || (vf >= adapter->num_vfs))
|
|
|
+ return -EINVAL;
|
|
|
+ adapter->vfinfo[vf].pf_set_mac = true;
|
|
|
+ dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf);
|
|
|
+ dev_info(&adapter->pdev->dev, "Reload the VF driver to make this"
|
|
|
+ " change effective.");
|
|
|
+ if (test_bit(__IXGBE_DOWN, &adapter->state)) {
|
|
|
+ dev_warn(&adapter->pdev->dev, "The VF MAC address has been set,"
|
|
|
+ " but the PF device is not up.\n");
|
|
|
+ dev_warn(&adapter->pdev->dev, "Bring the PF device up before"
|
|
|
+ " attempting to use the VF device.\n");
|
|
|
+ }
|
|
|
+ return ixgbe_set_vf_mac(adapter, vf, mac);
|
|
|
+}
|
|
|
+
|
|
|
+int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
|
|
|
+{
|
|
|
+ int err = 0;
|
|
|
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
|
|
+
|
|
|
+ if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7))
|
|
|
+ return -EINVAL;
|
|
|
+ if (vlan || qos) {
|
|
|
+ err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
|
|
|
+ if (err)
|
|
|
+ goto out;
|
|
|
+ ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
|
|
|
+ ixgbe_set_vmolr(&adapter->hw, vf, false);
|
|
|
+ adapter->vfinfo[vf].pf_vlan = vlan;
|
|
|
+ adapter->vfinfo[vf].pf_qos = qos;
|
|
|
+ dev_info(&adapter->pdev->dev,
|
|
|
+ "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf);
|
|
|
+ if (test_bit(__IXGBE_DOWN, &adapter->state)) {
|
|
|
+ dev_warn(&adapter->pdev->dev,
|
|
|
+ "The VF VLAN has been set,"
|
|
|
+ " but the PF device is not up.\n");
|
|
|
+ dev_warn(&adapter->pdev->dev,
|
|
|
+ "Bring the PF device up before"
|
|
|
+ " attempting to use the VF device.\n");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ err = ixgbe_set_vf_vlan(adapter, false,
|
|
|
+ adapter->vfinfo[vf].pf_vlan, vf);
|
|
|
+ ixgbe_set_vmvir(adapter, vlan, vf);
|
|
|
+ ixgbe_set_vmolr(&adapter->hw, vf, true);
|
|
|
+ adapter->vfinfo[vf].pf_vlan = 0;
|
|
|
+ adapter->vfinfo[vf].pf_qos = 0;
|
|
|
+ }
|
|
|
+out:
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
|
|
|
+{
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+}
|
|
|
+
|
|
|
+int ixgbe_ndo_get_vf_config(struct net_device *netdev,
|
|
|
+ int vf, struct ifla_vf_info *ivi)
|
|
|
+{
|
|
|
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
|
|
|
+ if (vf >= adapter->num_vfs)
|
|
|
+ return -EINVAL;
|
|
|
+ ivi->vf = vf;
|
|
|
+ memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN);
|
|
|
+ ivi->tx_rate = 0;
|
|
|
+ ivi->vlan = adapter->vfinfo[vf].pf_vlan;
|
|
|
+ ivi->qos = adapter->vfinfo[vf].pf_qos;
|
|
|
+ return 0;
|
|
|
+}
|