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/ixgbe_sriov.c | |
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/ixgbe_sriov.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_sriov.c | 96 |
1 files changed, 94 insertions, 2 deletions
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, |