diff options
author | Greg Rose <gregory.v.rose@intel.com> | 2011-05-12 21:33:48 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-05-14 20:53:09 -0400 |
commit | a1cbb15c13971bd5d41626e9e5ced9f9de132c47 (patch) | |
tree | d00386651afb90fc4e776f923fa454383cdfa46d /drivers/net/ixgbe | |
parent | 46ec20ff7d6f9f011e06d58e4e87153ed8c893ed (diff) |
ixgbe: Add macvlan support for VF
Add infrastructure in the PF driver to support macvlan in the VF driver.
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>
Diffstat (limited to 'drivers/net/ixgbe')
-rw-r--r-- | drivers/net/ixgbe/ixgbe.h | 13 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 28 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_mbx.h | 1 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_sriov.c | 96 |
4 files changed, 134 insertions, 4 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index 37ff531d59c0..91c15403c6bb 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -106,6 +106,7 @@ | |||
106 | #define IXGBE_MAX_VF_FUNCTIONS 64 | 106 | #define IXGBE_MAX_VF_FUNCTIONS 64 |
107 | #define IXGBE_MAX_VFTA_ENTRIES 128 | 107 | #define IXGBE_MAX_VFTA_ENTRIES 128 |
108 | #define MAX_EMULATION_MAC_ADDRS 16 | 108 | #define MAX_EMULATION_MAC_ADDRS 16 |
109 | #define IXGBE_MAX_PF_MACVLANS 15 | ||
109 | #define VMDQ_P(p) ((p) + adapter->num_vfs) | 110 | #define VMDQ_P(p) ((p) + adapter->num_vfs) |
110 | 111 | ||
111 | struct vf_data_storage { | 112 | struct vf_data_storage { |
@@ -121,6 +122,15 @@ struct vf_data_storage { | |||
121 | u16 tx_rate; | 122 | u16 tx_rate; |
122 | }; | 123 | }; |
123 | 124 | ||
125 | struct vf_macvlans { | ||
126 | struct list_head l; | ||
127 | int vf; | ||
128 | int rar_entry; | ||
129 | bool free; | ||
130 | bool is_macvlan; | ||
131 | u8 vf_macvlan[ETH_ALEN]; | ||
132 | }; | ||
133 | |||
124 | /* wrapper around a pointer to a socket buffer, | 134 | /* wrapper around a pointer to a socket buffer, |
125 | * so a DMA handle can be stored along with the buffer */ | 135 | * so a DMA handle can be stored along with the buffer */ |
126 | struct ixgbe_tx_buffer { | 136 | struct ixgbe_tx_buffer { |
@@ -471,6 +481,9 @@ struct ixgbe_adapter { | |||
471 | unsigned int num_vfs; | 481 | unsigned int num_vfs; |
472 | struct vf_data_storage *vfinfo; | 482 | struct vf_data_storage *vfinfo; |
473 | int vf_rate_link_speed; | 483 | int vf_rate_link_speed; |
484 | struct vf_macvlans vf_mvs; | ||
485 | struct vf_macvlans *mv_list; | ||
486 | bool antispoofing_enabled; | ||
474 | }; | 487 | }; |
475 | 488 | ||
476 | enum ixbge_state_t { | 489 | enum ixbge_state_t { |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index a3e384bc50fe..f8196e0d2745 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -3188,7 +3188,9 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter) | |||
3188 | /* enable Tx loopback for VF/PF communication */ | 3188 | /* enable Tx loopback for VF/PF communication */ |
3189 | IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); | 3189 | IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN); |
3190 | /* Enable MAC Anti-Spoofing */ | 3190 | /* Enable MAC Anti-Spoofing */ |
3191 | hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0), | 3191 | hw->mac.ops.set_mac_anti_spoofing(hw, |
3192 | (adapter->antispoofing_enabled = | ||
3193 | (adapter->num_vfs != 0)), | ||
3192 | adapter->num_vfs); | 3194 | adapter->num_vfs); |
3193 | } | 3195 | } |
3194 | 3196 | ||
@@ -3497,7 +3499,7 @@ static int ixgbe_write_uc_addr_list(struct net_device *netdev) | |||
3497 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 3499 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
3498 | struct ixgbe_hw *hw = &adapter->hw; | 3500 | struct ixgbe_hw *hw = &adapter->hw; |
3499 | unsigned int vfn = adapter->num_vfs; | 3501 | unsigned int vfn = adapter->num_vfs; |
3500 | unsigned int rar_entries = hw->mac.num_rar_entries - (vfn + 1); | 3502 | unsigned int rar_entries = IXGBE_MAX_PF_MACVLANS; |
3501 | int count = 0; | 3503 | int count = 0; |
3502 | 3504 | ||
3503 | /* return ENOMEM indicating insufficient memory for addresses */ | 3505 | /* return ENOMEM indicating insufficient memory for addresses */ |
@@ -7107,6 +7109,8 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, | |||
7107 | #ifdef CONFIG_PCI_IOV | 7109 | #ifdef CONFIG_PCI_IOV |
7108 | struct ixgbe_hw *hw = &adapter->hw; | 7110 | struct ixgbe_hw *hw = &adapter->hw; |
7109 | int err; | 7111 | int err; |
7112 | int num_vf_macvlans, i; | ||
7113 | struct vf_macvlans *mv_list; | ||
7110 | 7114 | ||
7111 | if (hw->mac.type == ixgbe_mac_82598EB || !max_vfs) | 7115 | if (hw->mac.type == ixgbe_mac_82598EB || !max_vfs) |
7112 | return; | 7116 | return; |
@@ -7123,6 +7127,26 @@ static void __devinit ixgbe_probe_vf(struct ixgbe_adapter *adapter, | |||
7123 | e_err(probe, "Failed to enable PCI sriov: %d\n", err); | 7127 | e_err(probe, "Failed to enable PCI sriov: %d\n", err); |
7124 | goto err_novfs; | 7128 | goto err_novfs; |
7125 | } | 7129 | } |
7130 | |||
7131 | num_vf_macvlans = hw->mac.num_rar_entries - | ||
7132 | (IXGBE_MAX_PF_MACVLANS + 1 + adapter->num_vfs); | ||
7133 | |||
7134 | adapter->mv_list = mv_list = kcalloc(num_vf_macvlans, | ||
7135 | sizeof(struct vf_macvlans), | ||
7136 | GFP_KERNEL); | ||
7137 | if (mv_list) { | ||
7138 | /* Initialize list of VF macvlans */ | ||
7139 | INIT_LIST_HEAD(&adapter->vf_mvs.l); | ||
7140 | for (i = 0; i < num_vf_macvlans; i++) { | ||
7141 | mv_list->vf = -1; | ||
7142 | mv_list->free = true; | ||
7143 | mv_list->rar_entry = hw->mac.num_rar_entries - | ||
7144 | (i + adapter->num_vfs + 1); | ||
7145 | list_add(&mv_list->l, &adapter->vf_mvs.l); | ||
7146 | mv_list++; | ||
7147 | } | ||
7148 | } | ||
7149 | |||
7126 | /* If call to enable VFs succeeded then allocate memory | 7150 | /* If call to enable VFs succeeded then allocate memory |
7127 | * for per VF control structures. | 7151 | * for per VF control structures. |
7128 | */ | 7152 | */ |
diff --git a/drivers/net/ixgbe/ixgbe_mbx.h b/drivers/net/ixgbe/ixgbe_mbx.h index f53dc5bb28b7..b239bdac38da 100644 --- a/drivers/net/ixgbe/ixgbe_mbx.h +++ b/drivers/net/ixgbe/ixgbe_mbx.h | |||
@@ -67,6 +67,7 @@ | |||
67 | #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ | 67 | #define IXGBE_VF_SET_MULTICAST 0x03 /* VF requests PF to set MC addr */ |
68 | #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ | 68 | #define IXGBE_VF_SET_VLAN 0x04 /* VF requests PF to set VLAN */ |
69 | #define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ | 69 | #define IXGBE_VF_SET_LPE 0x05 /* VF requests PF to set VMOLR.LPE */ |
70 | #define IXGBE_VF_SET_MACVLAN 0x06 /* VF requests PF for unicast filter */ | ||
70 | 71 | ||
71 | /* length of permanent address message returned from PF */ | 72 | /* length of permanent address message returned from PF */ |
72 | #define IXGBE_VF_PERMADDR_MSG_LEN 4 | 73 | #define IXGBE_VF_PERMADDR_MSG_LEN 4 |
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index 47650278d414..9f972460e780 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c | |||
@@ -82,6 +82,21 @@ static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, | |||
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
84 | 84 | ||
85 | static void ixgbe_restore_vf_macvlans(struct ixgbe_adapter *adapter) | ||
86 | { | ||
87 | struct ixgbe_hw *hw = &adapter->hw; | ||
88 | struct list_head *pos; | ||
89 | struct vf_macvlans *entry; | ||
90 | |||
91 | list_for_each(pos, &adapter->vf_mvs.l) { | ||
92 | entry = list_entry(pos, struct vf_macvlans, l); | ||
93 | if (entry->free == false) | ||
94 | hw->mac.ops.set_rar(hw, entry->rar_entry, | ||
95 | entry->vf_macvlan, | ||
96 | entry->vf, IXGBE_RAH_AV); | ||
97 | } | ||
98 | } | ||
99 | |||
85 | void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) | 100 | void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) |
86 | { | 101 | { |
87 | struct ixgbe_hw *hw = &adapter->hw; | 102 | struct ixgbe_hw *hw = &adapter->hw; |
@@ -102,6 +117,9 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) | |||
102 | IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); | 117 | IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); |
103 | } | 118 | } |
104 | } | 119 | } |
120 | |||
121 | /* Restore any VF macvlans */ | ||
122 | ixgbe_restore_vf_macvlans(adapter); | ||
105 | } | 123 | } |
106 | 124 | ||
107 | static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, | 125 | static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, |
@@ -200,6 +218,61 @@ static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter, | |||
200 | return 0; | 218 | return 0; |
201 | } | 219 | } |
202 | 220 | ||
221 | static int ixgbe_set_vf_macvlan(struct ixgbe_adapter *adapter, | ||
222 | int vf, int index, unsigned char *mac_addr) | ||
223 | { | ||
224 | struct ixgbe_hw *hw = &adapter->hw; | ||
225 | struct list_head *pos; | ||
226 | struct vf_macvlans *entry; | ||
227 | |||
228 | if (index <= 1) { | ||
229 | list_for_each(pos, &adapter->vf_mvs.l) { | ||
230 | entry = list_entry(pos, struct vf_macvlans, l); | ||
231 | if (entry->vf == vf) { | ||
232 | entry->vf = -1; | ||
233 | entry->free = true; | ||
234 | entry->is_macvlan = false; | ||
235 | hw->mac.ops.clear_rar(hw, entry->rar_entry); | ||
236 | } | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * If index was zero then we were asked to clear the uc list | ||
242 | * for the VF. We're done. | ||
243 | */ | ||
244 | if (!index) | ||
245 | return 0; | ||
246 | |||
247 | entry = NULL; | ||
248 | |||
249 | list_for_each(pos, &adapter->vf_mvs.l) { | ||
250 | entry = list_entry(pos, struct vf_macvlans, l); | ||
251 | if (entry->free) | ||
252 | break; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * If we traversed the entire list and didn't find a free entry | ||
257 | * then we're out of space on the RAR table. Also entry may | ||
258 | * be NULL because the original memory allocation for the list | ||
259 | * failed, which is not fatal but does mean we can't support | ||
260 | * VF requests for MACVLAN because we couldn't allocate | ||
261 | * memory for the list management required. | ||
262 | */ | ||
263 | if (!entry || !entry->free) | ||
264 | return -ENOSPC; | ||
265 | |||
266 | entry->free = false; | ||
267 | entry->is_macvlan = true; | ||
268 | entry->vf = vf; | ||
269 | memcpy(entry->vf_macvlan, mac_addr, ETH_ALEN); | ||
270 | |||
271 | hw->mac.ops.set_rar(hw, entry->rar_entry, mac_addr, vf, IXGBE_RAH_AV); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
203 | int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) | 276 | int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask) |
204 | { | 277 | { |
205 | unsigned char vf_mac_addr[6]; | 278 | unsigned char vf_mac_addr[6]; |
@@ -256,7 +329,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) | |||
256 | s32 retval; | 329 | s32 retval; |
257 | int entries; | 330 | int entries; |
258 | u16 *hash_list; | 331 | u16 *hash_list; |
259 | int add, vid; | 332 | int add, vid, index; |
260 | u8 *new_mac; | 333 | u8 *new_mac; |
261 | 334 | ||
262 | retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); | 335 | retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf); |
@@ -345,6 +418,24 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) | |||
345 | retval = ixgbe_set_vf_vlan(adapter, add, vid, vf); | 418 | retval = ixgbe_set_vf_vlan(adapter, add, vid, vf); |
346 | } | 419 | } |
347 | break; | 420 | break; |
421 | case IXGBE_VF_SET_MACVLAN: | ||
422 | index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> | ||
423 | IXGBE_VT_MSGINFO_SHIFT; | ||
424 | /* | ||
425 | * If the VF is allowed to set MAC filters then turn off | ||
426 | * anti-spoofing to avoid false positives. An index | ||
427 | * greater than 0 will indicate the VF is setting a | ||
428 | * macvlan MAC filter. | ||
429 | */ | ||
430 | if (index > 0 && adapter->antispoofing_enabled) { | ||
431 | hw->mac.ops.set_mac_anti_spoofing(hw, false, | ||
432 | adapter->num_vfs); | ||
433 | hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf); | ||
434 | adapter->antispoofing_enabled = false; | ||
435 | } | ||
436 | retval = ixgbe_set_vf_macvlan(adapter, vf, index, | ||
437 | (unsigned char *)(&msgbuf[1])); | ||
438 | break; | ||
348 | default: | 439 | default: |
349 | e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); | 440 | e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]); |
350 | retval = IXGBE_ERR_MBX; | 441 | retval = IXGBE_ERR_MBX; |
@@ -452,7 +543,8 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) | |||
452 | goto out; | 543 | goto out; |
453 | ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); | 544 | ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); |
454 | ixgbe_set_vmolr(hw, vf, false); | 545 | ixgbe_set_vmolr(hw, vf, false); |
455 | hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); | 546 | if (adapter->antispoofing_enabled) |
547 | hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf); | ||
456 | adapter->vfinfo[vf].pf_vlan = vlan; | 548 | adapter->vfinfo[vf].pf_vlan = vlan; |
457 | adapter->vfinfo[vf].pf_qos = qos; | 549 | adapter->vfinfo[vf].pf_qos = qos; |
458 | dev_info(&adapter->pdev->dev, | 550 | dev_info(&adapter->pdev->dev, |