提交 7f01648a 编写于 作者: G Greg Rose 提交者: David S. Miller

ixgbe: Add support for VF MAC and VLAN configuration

Add support for the "ip link set" and "ip link show" commands that allow
configuration of the virtual functions' MAC and port VLAN via user space
command line.
Signed-off-by: NGreg Rose <gregory.v.rose@intel.com>
Signed-off-by: NJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 f0412776
...@@ -111,7 +111,10 @@ struct vf_data_storage { ...@@ -111,7 +111,10 @@ struct vf_data_storage {
u16 default_vf_vlan_id; u16 default_vf_vlan_id;
u16 vlans_enabled; u16 vlans_enabled;
bool clear_to_send; bool clear_to_send;
bool pf_set_mac;
int rar; int rar;
u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos;
}; };
/* wrapper around a pointer to a socket buffer, /* wrapper around a pointer to a socket buffer,
......
...@@ -6311,6 +6311,10 @@ static const struct net_device_ops ixgbe_netdev_ops = { ...@@ -6311,6 +6311,10 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid, .ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid, .ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid,
.ndo_do_ioctl = ixgbe_ioctl, .ndo_do_ioctl = ixgbe_ioctl,
.ndo_set_vf_mac = ixgbe_ndo_set_vf_mac,
.ndo_set_vf_vlan = ixgbe_ndo_set_vf_vlan,
.ndo_set_vf_tx_rate = ixgbe_ndo_set_vf_bw,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
#ifdef CONFIG_NET_POLL_CONTROLLER #ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = ixgbe_netpoll, .ndo_poll_controller = ixgbe_netpoll,
#endif #endif
......
...@@ -126,13 +126,34 @@ void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) ...@@ -126,13 +126,34 @@ void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); 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) inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
/* reset offloads to defaults */ /* 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 */ /* reset multicast table array for vf */
adapter->vfinfo[vf].num_vf_mc_hashes = 0; 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) ...@@ -266,10 +287,12 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
case IXGBE_VF_SET_MAC_ADDR: case IXGBE_VF_SET_MAC_ADDR:
{ {
u8 *new_mac = ((u8 *)(&msgbuf[1])); 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); ixgbe_set_vf_mac(adapter, vf, new_mac);
else else
retval = -1; ixgbe_set_vf_mac(adapter,
vf, adapter->vfinfo[vf].vf_mac_addresses);
} }
break; break;
case IXGBE_VF_SET_MULTICAST: case IXGBE_VF_SET_MULTICAST:
...@@ -363,3 +386,76 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter) ...@@ -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;
}
...@@ -42,6 +42,12 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask); ...@@ -42,6 +42,12 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter); void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);
void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter); void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter);
void ixgbe_dump_registers(struct ixgbe_adapter *adapter); void ixgbe_dump_registers(struct ixgbe_adapter *adapter);
int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int queue, u8 *mac);
int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int queue, u16 vlan,
u8 qos);
int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
int ixgbe_ndo_get_vf_config(struct net_device *netdev,
int vf, struct ifla_vf_info *ivi);
#endif /* _IXGBE_SRIOV_H_ */ #endif /* _IXGBE_SRIOV_H_ */
...@@ -219,6 +219,7 @@ ...@@ -219,6 +219,7 @@
#define IXGBE_MTQC 0x08120 #define IXGBE_MTQC 0x08120
#define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */ #define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */
#define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */ #define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */
#define IXGBE_VMVIR(_i) (0x08000 + ((_i) * 4)) /* 64 of these (0-63) */
#define IXGBE_VT_CTL 0x051B0 #define IXGBE_VT_CTL 0x051B0
#define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4)) #define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4))
#define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4)) #define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4))
...@@ -1311,6 +1312,10 @@ ...@@ -1311,6 +1312,10 @@
#define IXGBE_VLVF_ENTRIES 64 #define IXGBE_VLVF_ENTRIES 64
#define IXGBE_VLVF_VLANID_MASK 0x00000FFF #define IXGBE_VLVF_VLANID_MASK 0x00000FFF
/* Per VF Port VLAN insertion rules */
#define IXGBE_VMVIR_VLANA_DEFAULT 0x40000000 /* Always use default VLAN */
#define IXGBE_VMVIR_VLANA_NEVER 0x80000000 /* Never insert VLAN tag */
#define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */ #define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */
/* STATUS Bit Masks */ /* STATUS Bit Masks */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册