diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_sriov.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_sriov.c | 137 |
1 files changed, 117 insertions, 20 deletions
diff --git a/drivers/net/ixgbe/ixgbe_sriov.c b/drivers/net/ixgbe/ixgbe_sriov.c index d4cd20f30199..f6cee94ec8e8 100644 --- a/drivers/net/ixgbe/ixgbe_sriov.c +++ b/drivers/net/ixgbe/ixgbe_sriov.c | |||
@@ -48,7 +48,11 @@ int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, | |||
48 | int entries, u16 *hash_list, u32 vf) | 48 | int entries, u16 *hash_list, u32 vf) |
49 | { | 49 | { |
50 | struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; | 50 | struct vf_data_storage *vfinfo = &adapter->vfinfo[vf]; |
51 | struct ixgbe_hw *hw = &adapter->hw; | ||
51 | int i; | 52 | int i; |
53 | u32 vector_bit; | ||
54 | u32 vector_reg; | ||
55 | u32 mta_reg; | ||
52 | 56 | ||
53 | /* only so many hash values supported */ | 57 | /* only so many hash values supported */ |
54 | entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES); | 58 | entries = min(entries, IXGBE_MAX_VF_MC_ENTRIES); |
@@ -68,8 +72,13 @@ int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter, | |||
68 | vfinfo->vf_mc_hashes[i] = hash_list[i];; | 72 | vfinfo->vf_mc_hashes[i] = hash_list[i];; |
69 | } | 73 | } |
70 | 74 | ||
71 | /* Flush and reset the mta with the new values */ | 75 | for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { |
72 | ixgbe_set_rx_mode(adapter->netdev); | 76 | vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F; |
77 | vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F; | ||
78 | mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg)); | ||
79 | mta_reg |= (1 << vector_bit); | ||
80 | IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg); | ||
81 | } | ||
73 | 82 | ||
74 | return 0; | 83 | return 0; |
75 | } | 84 | } |
@@ -98,38 +107,51 @@ void ixgbe_restore_vf_multicasts(struct ixgbe_adapter *adapter) | |||
98 | 107 | ||
99 | int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf) | 108 | int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid, u32 vf) |
100 | { | 109 | { |
101 | u32 ctrl; | ||
102 | |||
103 | /* Check if global VLAN already set, if not set it */ | ||
104 | ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL); | ||
105 | if (!(ctrl & IXGBE_VLNCTRL_VFE)) { | ||
106 | /* enable VLAN tag insert/strip */ | ||
107 | ctrl |= IXGBE_VLNCTRL_VFE; | ||
108 | ctrl &= ~IXGBE_VLNCTRL_CFIEN; | ||
109 | IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl); | ||
110 | } | ||
111 | |||
112 | return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); | 110 | return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add); |
113 | } | 111 | } |
114 | 112 | ||
115 | 113 | ||
116 | void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf) | 114 | void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe) |
117 | { | 115 | { |
118 | u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); | 116 | u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf)); |
119 | vmolr |= (IXGBE_VMOLR_AUPE | | 117 | vmolr |= (IXGBE_VMOLR_ROMPE | |
120 | IXGBE_VMOLR_ROMPE | | ||
121 | IXGBE_VMOLR_ROPE | | 118 | IXGBE_VMOLR_ROPE | |
122 | IXGBE_VMOLR_BAM); | 119 | IXGBE_VMOLR_BAM); |
120 | if (aupe) | ||
121 | vmolr |= IXGBE_VMOLR_AUPE; | ||
122 | else | ||
123 | vmolr &= ~IXGBE_VMOLR_AUPE; | ||
123 | IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); | 124 | IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr); |
124 | } | 125 | } |
125 | 126 | ||
127 | static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf) | ||
128 | { | ||
129 | struct ixgbe_hw *hw = &adapter->hw; | ||
130 | |||
131 | if (vid) | ||
132 | IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), | ||
133 | (vid | IXGBE_VMVIR_VLANA_DEFAULT)); | ||
134 | else | ||
135 | IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0); | ||
136 | } | ||
137 | |||
126 | inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) | 138 | inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf) |
127 | { | 139 | { |
128 | struct ixgbe_hw *hw = &adapter->hw; | 140 | struct ixgbe_hw *hw = &adapter->hw; |
129 | 141 | ||
130 | /* reset offloads to defaults */ | 142 | /* reset offloads to defaults */ |
131 | ixgbe_set_vmolr(hw, vf); | 143 | if (adapter->vfinfo[vf].pf_vlan) { |
132 | 144 | ixgbe_set_vf_vlan(adapter, true, | |
145 | adapter->vfinfo[vf].pf_vlan, vf); | ||
146 | ixgbe_set_vmvir(adapter, | ||
147 | (adapter->vfinfo[vf].pf_vlan | | ||
148 | (adapter->vfinfo[vf].pf_qos << | ||
149 | VLAN_PRIO_SHIFT)), vf); | ||
150 | ixgbe_set_vmolr(hw, vf, false); | ||
151 | } else { | ||
152 | ixgbe_set_vmvir(adapter, 0, vf); | ||
153 | ixgbe_set_vmolr(hw, vf, true); | ||
154 | } | ||
133 | 155 | ||
134 | /* reset multicast table array for vf */ | 156 | /* reset multicast table array for vf */ |
135 | adapter->vfinfo[vf].num_vf_mc_hashes = 0; | 157 | adapter->vfinfo[vf].num_vf_mc_hashes = 0; |
@@ -263,10 +285,12 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf) | |||
263 | case IXGBE_VF_SET_MAC_ADDR: | 285 | case IXGBE_VF_SET_MAC_ADDR: |
264 | { | 286 | { |
265 | u8 *new_mac = ((u8 *)(&msgbuf[1])); | 287 | u8 *new_mac = ((u8 *)(&msgbuf[1])); |
266 | if (is_valid_ether_addr(new_mac)) | 288 | if (is_valid_ether_addr(new_mac) && |
289 | !adapter->vfinfo[vf].pf_set_mac) | ||
267 | ixgbe_set_vf_mac(adapter, vf, new_mac); | 290 | ixgbe_set_vf_mac(adapter, vf, new_mac); |
268 | else | 291 | else |
269 | retval = -1; | 292 | ixgbe_set_vf_mac(adapter, |
293 | vf, adapter->vfinfo[vf].vf_mac_addresses); | ||
270 | } | 294 | } |
271 | break; | 295 | break; |
272 | case IXGBE_VF_SET_MULTICAST: | 296 | case IXGBE_VF_SET_MULTICAST: |
@@ -360,3 +384,76 @@ void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter) | |||
360 | } | 384 | } |
361 | } | 385 | } |
362 | 386 | ||
387 | int ixgbe_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) | ||
388 | { | ||
389 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
390 | if (!is_valid_ether_addr(mac) || (vf >= adapter->num_vfs)) | ||
391 | return -EINVAL; | ||
392 | adapter->vfinfo[vf].pf_set_mac = true; | ||
393 | dev_info(&adapter->pdev->dev, "setting MAC %pM on VF %d\n", mac, vf); | ||
394 | dev_info(&adapter->pdev->dev, "Reload the VF driver to make this" | ||
395 | " change effective."); | ||
396 | if (test_bit(__IXGBE_DOWN, &adapter->state)) { | ||
397 | dev_warn(&adapter->pdev->dev, "The VF MAC address has been set," | ||
398 | " but the PF device is not up.\n"); | ||
399 | dev_warn(&adapter->pdev->dev, "Bring the PF device up before" | ||
400 | " attempting to use the VF device.\n"); | ||
401 | } | ||
402 | return ixgbe_set_vf_mac(adapter, vf, mac); | ||
403 | } | ||
404 | |||
405 | int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) | ||
406 | { | ||
407 | int err = 0; | ||
408 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
409 | |||
410 | if ((vf >= adapter->num_vfs) || (vlan > 4095) || (qos > 7)) | ||
411 | return -EINVAL; | ||
412 | if (vlan || qos) { | ||
413 | err = ixgbe_set_vf_vlan(adapter, true, vlan, vf); | ||
414 | if (err) | ||
415 | goto out; | ||
416 | ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf); | ||
417 | ixgbe_set_vmolr(&adapter->hw, vf, false); | ||
418 | adapter->vfinfo[vf].pf_vlan = vlan; | ||
419 | adapter->vfinfo[vf].pf_qos = qos; | ||
420 | dev_info(&adapter->pdev->dev, | ||
421 | "Setting VLAN %d, QOS 0x%x on VF %d\n", vlan, qos, vf); | ||
422 | if (test_bit(__IXGBE_DOWN, &adapter->state)) { | ||
423 | dev_warn(&adapter->pdev->dev, | ||
424 | "The VF VLAN has been set," | ||
425 | " but the PF device is not up.\n"); | ||
426 | dev_warn(&adapter->pdev->dev, | ||
427 | "Bring the PF device up before" | ||
428 | " attempting to use the VF device.\n"); | ||
429 | } | ||
430 | } else { | ||
431 | err = ixgbe_set_vf_vlan(adapter, false, | ||
432 | adapter->vfinfo[vf].pf_vlan, vf); | ||
433 | ixgbe_set_vmvir(adapter, vlan, vf); | ||
434 | ixgbe_set_vmolr(&adapter->hw, vf, true); | ||
435 | adapter->vfinfo[vf].pf_vlan = 0; | ||
436 | adapter->vfinfo[vf].pf_qos = 0; | ||
437 | } | ||
438 | out: | ||
439 | return err; | ||
440 | } | ||
441 | |||
442 | int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate) | ||
443 | { | ||
444 | return -EOPNOTSUPP; | ||
445 | } | ||
446 | |||
447 | int ixgbe_ndo_get_vf_config(struct net_device *netdev, | ||
448 | int vf, struct ifla_vf_info *ivi) | ||
449 | { | ||
450 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | ||
451 | if (vf >= adapter->num_vfs) | ||
452 | return -EINVAL; | ||
453 | ivi->vf = vf; | ||
454 | memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN); | ||
455 | ivi->tx_rate = 0; | ||
456 | ivi->vlan = adapter->vfinfo[vf].pf_vlan; | ||
457 | ivi->qos = adapter->vfinfo[vf].pf_qos; | ||
458 | return 0; | ||
459 | } | ||