]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #include <stdio.h> | |
35 | #include <errno.h> | |
36 | #include <stdint.h> | |
37 | #include <stdlib.h> | |
38 | #include <unistd.h> | |
39 | #include <stdarg.h> | |
40 | #include <inttypes.h> | |
41 | ||
42 | #include <rte_interrupts.h> | |
43 | #include <rte_log.h> | |
44 | #include <rte_debug.h> | |
45 | #include <rte_eal.h> | |
46 | #include <rte_ether.h> | |
47 | #include <rte_ethdev.h> | |
48 | #include <rte_memcpy.h> | |
49 | #include <rte_malloc.h> | |
50 | #include <rte_random.h> | |
51 | ||
52 | #include "base/e1000_defines.h" | |
53 | #include "base/e1000_regs.h" | |
54 | #include "base/e1000_hw.h" | |
55 | #include "e1000_ethdev.h" | |
56 | ||
57 | static inline uint16_t | |
58 | dev_num_vf(struct rte_eth_dev *eth_dev) | |
59 | { | |
60 | return eth_dev->pci_dev->max_vfs; | |
61 | } | |
62 | ||
63 | static inline | |
64 | int igb_vf_perm_addr_gen(struct rte_eth_dev *dev, uint16_t vf_num) | |
65 | { | |
66 | unsigned char vf_mac_addr[ETHER_ADDR_LEN]; | |
67 | struct e1000_vf_info *vfinfo = | |
68 | *E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); | |
69 | uint16_t vfn; | |
70 | ||
71 | for (vfn = 0; vfn < vf_num; vfn++) { | |
72 | eth_random_addr(vf_mac_addr); | |
73 | /* keep the random address as default */ | |
74 | memcpy(vfinfo[vfn].vf_mac_addresses, vf_mac_addr, | |
75 | ETHER_ADDR_LEN); | |
76 | } | |
77 | ||
78 | return 0; | |
79 | } | |
80 | ||
81 | static inline int | |
82 | igb_mb_intr_setup(struct rte_eth_dev *dev) | |
83 | { | |
84 | struct e1000_interrupt *intr = | |
85 | E1000_DEV_PRIVATE_TO_INTR(dev->data->dev_private); | |
86 | ||
87 | intr->mask |= E1000_ICR_VMMB; | |
88 | ||
89 | return 0; | |
90 | } | |
91 | ||
92 | void igb_pf_host_init(struct rte_eth_dev *eth_dev) | |
93 | { | |
94 | struct e1000_vf_info **vfinfo = | |
95 | E1000_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private); | |
96 | struct e1000_hw *hw = | |
97 | E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); | |
98 | uint16_t vf_num; | |
99 | uint8_t nb_queue; | |
100 | ||
101 | RTE_ETH_DEV_SRIOV(eth_dev).active = 0; | |
102 | if (0 == (vf_num = dev_num_vf(eth_dev))) | |
103 | return; | |
104 | ||
105 | if (hw->mac.type == e1000_i350) | |
106 | nb_queue = 1; | |
107 | else if(hw->mac.type == e1000_82576) | |
108 | /* per datasheet, it should be 2, but 1 seems correct */ | |
109 | nb_queue = 1; | |
110 | else | |
111 | return; | |
112 | ||
113 | *vfinfo = rte_zmalloc("vf_info", sizeof(struct e1000_vf_info) * vf_num, 0); | |
114 | if (*vfinfo == NULL) | |
115 | rte_panic("Cannot allocate memory for private VF data\n"); | |
116 | ||
117 | RTE_ETH_DEV_SRIOV(eth_dev).active = ETH_8_POOLS; | |
118 | RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = nb_queue; | |
119 | RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = vf_num; | |
120 | RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = (uint16_t)(vf_num * nb_queue); | |
121 | ||
122 | igb_vf_perm_addr_gen(eth_dev, vf_num); | |
123 | ||
124 | /* set mb interrupt mask */ | |
125 | igb_mb_intr_setup(eth_dev); | |
126 | ||
127 | return; | |
128 | } | |
129 | ||
130 | void igb_pf_host_uninit(struct rte_eth_dev *dev) | |
131 | { | |
132 | struct e1000_vf_info **vfinfo; | |
133 | uint16_t vf_num; | |
134 | ||
135 | PMD_INIT_FUNC_TRACE(); | |
136 | ||
137 | vfinfo = E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); | |
138 | ||
139 | RTE_ETH_DEV_SRIOV(dev).active = 0; | |
140 | RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = 0; | |
141 | RTE_ETH_DEV_SRIOV(dev).def_vmdq_idx = 0; | |
142 | RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx = 0; | |
143 | ||
144 | vf_num = dev_num_vf(dev); | |
145 | if (vf_num == 0) | |
146 | return; | |
147 | ||
148 | rte_free(*vfinfo); | |
149 | *vfinfo = NULL; | |
150 | } | |
151 | ||
152 | #define E1000_RAH_POOLSEL_SHIFT (18) | |
153 | int igb_pf_host_configure(struct rte_eth_dev *eth_dev) | |
154 | { | |
155 | uint32_t vtctl; | |
156 | uint16_t vf_num; | |
157 | struct e1000_hw *hw = | |
158 | E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); | |
159 | uint32_t vlanctrl; | |
160 | int i; | |
161 | uint32_t rah; | |
162 | ||
163 | if (0 == (vf_num = dev_num_vf(eth_dev))) | |
164 | return -1; | |
165 | ||
166 | /* enable VMDq and set the default pool for PF */ | |
167 | vtctl = E1000_READ_REG(hw, E1000_VT_CTL); | |
168 | vtctl &= ~E1000_VT_CTL_DEFAULT_POOL_MASK; | |
169 | vtctl |= RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx | |
170 | << E1000_VT_CTL_DEFAULT_POOL_SHIFT; | |
171 | vtctl |= E1000_VT_CTL_VM_REPL_EN; | |
172 | E1000_WRITE_REG(hw, E1000_VT_CTL, vtctl); | |
173 | ||
174 | /* Enable pools reserved to PF only */ | |
175 | E1000_WRITE_REG(hw, E1000_VFRE, (~0U) << vf_num); | |
176 | E1000_WRITE_REG(hw, E1000_VFTE, (~0U) << vf_num); | |
177 | ||
178 | /* PFDMA Tx General Switch Control Enables VMDQ loopback */ | |
179 | if (hw->mac.type == e1000_i350) | |
180 | E1000_WRITE_REG(hw, E1000_TXSWC, E1000_DTXSWC_VMDQ_LOOPBACK_EN); | |
181 | else | |
182 | E1000_WRITE_REG(hw, E1000_DTXSWC, E1000_DTXSWC_VMDQ_LOOPBACK_EN); | |
183 | ||
184 | /* clear VMDq map to perment rar 0 */ | |
185 | rah = E1000_READ_REG(hw, E1000_RAH(0)); | |
186 | rah &= ~ (0xFF << E1000_RAH_POOLSEL_SHIFT); | |
187 | E1000_WRITE_REG(hw, E1000_RAH(0), rah); | |
188 | ||
189 | /* clear VMDq map to scan rar 32 */ | |
190 | rah = E1000_READ_REG(hw, E1000_RAH(hw->mac.rar_entry_count)); | |
191 | rah &= ~ (0xFF << E1000_RAH_POOLSEL_SHIFT); | |
192 | E1000_WRITE_REG(hw, E1000_RAH(hw->mac.rar_entry_count), rah); | |
193 | ||
194 | /* set VMDq map to default PF pool */ | |
195 | rah = E1000_READ_REG(hw, E1000_RAH(0)); | |
196 | rah |= (0x1 << (RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx + | |
197 | E1000_RAH_POOLSEL_SHIFT)); | |
198 | E1000_WRITE_REG(hw, E1000_RAH(0), rah); | |
199 | ||
200 | /* | |
201 | * enable vlan filtering and allow all vlan tags through | |
202 | */ | |
203 | vlanctrl = E1000_READ_REG(hw, E1000_RCTL); | |
204 | vlanctrl |= E1000_RCTL_VFE ; /* enable vlan filters */ | |
205 | E1000_WRITE_REG(hw, E1000_RCTL, vlanctrl); | |
206 | ||
207 | /* VFTA - enable all vlan filters */ | |
208 | for (i = 0; i < IGB_VFTA_SIZE; i++) { | |
209 | E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, i, 0xFFFFFFFF); | |
210 | } | |
211 | ||
212 | /* Enable/Disable MAC Anti-Spoofing */ | |
213 | e1000_vmdq_set_anti_spoofing_pf(hw, FALSE, vf_num); | |
214 | ||
215 | return 0; | |
216 | } | |
217 | ||
218 | static void | |
219 | set_rx_mode(struct rte_eth_dev *dev) | |
220 | { | |
221 | struct rte_eth_dev_data *dev_data = dev->data; | |
222 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
223 | uint32_t fctrl, vmolr = E1000_VMOLR_BAM | E1000_VMOLR_AUPE; | |
224 | uint16_t vfn = dev_num_vf(dev); | |
225 | ||
226 | /* Check for Promiscuous and All Multicast modes */ | |
227 | fctrl = E1000_READ_REG(hw, E1000_RCTL); | |
228 | ||
229 | /* set all bits that we expect to always be set */ | |
230 | fctrl &= ~E1000_RCTL_SBP; /* disable store-bad-packets */ | |
231 | fctrl |= E1000_RCTL_BAM; | |
232 | ||
233 | /* clear the bits we are changing the status of */ | |
234 | fctrl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); | |
235 | ||
236 | if (dev_data->promiscuous) { | |
237 | fctrl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); | |
238 | vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_MPME); | |
239 | } else { | |
240 | if (dev_data->all_multicast) { | |
241 | fctrl |= E1000_RCTL_MPE; | |
242 | vmolr |= E1000_VMOLR_MPME; | |
243 | } else { | |
244 | vmolr |= E1000_VMOLR_ROMPE; | |
245 | } | |
246 | } | |
247 | ||
248 | if ((hw->mac.type == e1000_82576) || | |
249 | (hw->mac.type == e1000_i350)) { | |
250 | vmolr |= E1000_READ_REG(hw, E1000_VMOLR(vfn)) & | |
251 | ~(E1000_VMOLR_MPME | E1000_VMOLR_ROMPE | | |
252 | E1000_VMOLR_ROPE); | |
253 | E1000_WRITE_REG(hw, E1000_VMOLR(vfn), vmolr); | |
254 | } | |
255 | ||
256 | E1000_WRITE_REG(hw, E1000_RCTL, fctrl); | |
257 | } | |
258 | ||
259 | static inline void | |
260 | igb_vf_reset_event(struct rte_eth_dev *dev, uint16_t vf) | |
261 | { | |
262 | struct e1000_hw *hw = | |
263 | E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
264 | struct e1000_vf_info *vfinfo = | |
265 | *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); | |
266 | uint32_t vmolr = E1000_READ_REG(hw, E1000_VMOLR(vf)); | |
267 | ||
268 | vmolr |= (E1000_VMOLR_ROPE | E1000_VMOLR_ROMPE | | |
269 | E1000_VMOLR_BAM | E1000_VMOLR_AUPE); | |
270 | E1000_WRITE_REG(hw, E1000_VMOLR(vf), vmolr); | |
271 | ||
272 | E1000_WRITE_REG(hw, E1000_VMVIR(vf), 0); | |
273 | ||
274 | /* reset multicast table array for vf */ | |
275 | vfinfo[vf].num_vf_mc_hashes = 0; | |
276 | ||
277 | /* reset rx mode */ | |
278 | set_rx_mode(dev); | |
279 | } | |
280 | ||
281 | static inline void | |
282 | igb_vf_reset_msg(struct rte_eth_dev *dev, uint16_t vf) | |
283 | { | |
284 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
285 | uint32_t reg; | |
286 | ||
287 | /* enable transmit and receive for vf */ | |
288 | reg = E1000_READ_REG(hw, E1000_VFTE); | |
289 | reg |= (reg | (1 << vf)); | |
290 | E1000_WRITE_REG(hw, E1000_VFTE, reg); | |
291 | ||
292 | reg = E1000_READ_REG(hw, E1000_VFRE); | |
293 | reg |= (reg | (1 << vf)); | |
294 | E1000_WRITE_REG(hw, E1000_VFRE, reg); | |
295 | ||
296 | igb_vf_reset_event(dev, vf); | |
297 | } | |
298 | ||
299 | static int | |
300 | igb_vf_reset(struct rte_eth_dev *dev, uint16_t vf, uint32_t *msgbuf) | |
301 | { | |
302 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
303 | struct e1000_vf_info *vfinfo = | |
304 | *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); | |
305 | unsigned char *vf_mac = vfinfo[vf].vf_mac_addresses; | |
306 | int rar_entry = hw->mac.rar_entry_count - (vf + 1); | |
307 | uint8_t *new_mac = (uint8_t *)(&msgbuf[1]); | |
308 | uint32_t rah; | |
309 | ||
310 | igb_vf_reset_msg(dev, vf); | |
311 | ||
312 | hw->mac.ops.rar_set(hw, vf_mac, rar_entry); | |
313 | rah = E1000_READ_REG(hw, E1000_RAH(rar_entry)); | |
314 | rah |= (0x1 << (vf + E1000_RAH_POOLSEL_SHIFT)); | |
315 | E1000_WRITE_REG(hw, E1000_RAH(rar_entry), rah); | |
316 | ||
317 | /* reply to reset with ack and vf mac address */ | |
318 | msgbuf[0] = E1000_VF_RESET | E1000_VT_MSGTYPE_ACK; | |
319 | rte_memcpy(new_mac, vf_mac, ETHER_ADDR_LEN); | |
320 | e1000_write_mbx(hw, msgbuf, 3, vf); | |
321 | ||
322 | return 0; | |
323 | } | |
324 | ||
325 | static int | |
326 | igb_vf_set_mac_addr(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) | |
327 | { | |
328 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
329 | struct e1000_vf_info *vfinfo = | |
330 | *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); | |
331 | int rar_entry = hw->mac.rar_entry_count - (vf + 1); | |
332 | uint8_t *new_mac = (uint8_t *)(&msgbuf[1]); | |
333 | ||
334 | if (is_unicast_ether_addr((struct ether_addr *)new_mac)) { | |
335 | if (!is_zero_ether_addr((struct ether_addr *)new_mac)) | |
336 | rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac, | |
337 | sizeof(vfinfo[vf].vf_mac_addresses)); | |
338 | hw->mac.ops.rar_set(hw, new_mac, rar_entry); | |
339 | return 0; | |
340 | } | |
341 | return -1; | |
342 | } | |
343 | ||
344 | static int | |
345 | igb_vf_set_multicast(struct rte_eth_dev *dev, __rte_unused uint32_t vf, uint32_t *msgbuf) | |
346 | { | |
347 | int i; | |
348 | uint32_t vector_bit; | |
349 | uint32_t vector_reg; | |
350 | uint32_t mta_reg; | |
351 | int entries = (msgbuf[0] & E1000_VT_MSGINFO_MASK) >> | |
352 | E1000_VT_MSGINFO_SHIFT; | |
353 | uint16_t *hash_list = (uint16_t *)&msgbuf[1]; | |
354 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
355 | struct e1000_vf_info *vfinfo = | |
356 | *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); | |
357 | ||
358 | /* only so many hash values supported */ | |
359 | entries = RTE_MIN(entries, E1000_MAX_VF_MC_ENTRIES); | |
360 | ||
361 | /* | |
362 | * salt away the number of multi cast addresses assigned | |
363 | * to this VF for later use to restore when the PF multi cast | |
364 | * list changes | |
365 | */ | |
366 | vfinfo->num_vf_mc_hashes = (uint16_t)entries; | |
367 | ||
368 | /* | |
369 | * VFs are limited to using the MTA hash table for their multicast | |
370 | * addresses | |
371 | */ | |
372 | for (i = 0; i < entries; i++) { | |
373 | vfinfo->vf_mc_hashes[i] = hash_list[i]; | |
374 | } | |
375 | ||
376 | for (i = 0; i < vfinfo->num_vf_mc_hashes; i++) { | |
377 | vector_reg = (vfinfo->vf_mc_hashes[i] >> 5) & 0x7F; | |
378 | vector_bit = vfinfo->vf_mc_hashes[i] & 0x1F; | |
379 | mta_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, vector_reg); | |
380 | mta_reg |= (1 << vector_bit); | |
381 | E1000_WRITE_REG_ARRAY(hw, E1000_MTA, vector_reg, mta_reg); | |
382 | } | |
383 | ||
384 | return 0; | |
385 | } | |
386 | ||
387 | static int | |
388 | igb_vf_set_vlan(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) | |
389 | { | |
390 | int add, vid; | |
391 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
392 | struct e1000_vf_info *vfinfo = | |
393 | *(E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private)); | |
394 | uint32_t vid_idx, vid_bit, vfta; | |
395 | ||
396 | add = (msgbuf[0] & E1000_VT_MSGINFO_MASK) | |
397 | >> E1000_VT_MSGINFO_SHIFT; | |
398 | vid = (msgbuf[1] & E1000_VLVF_VLANID_MASK); | |
399 | ||
400 | if (add) | |
401 | vfinfo[vf].vlan_count++; | |
402 | else if (vfinfo[vf].vlan_count) | |
403 | vfinfo[vf].vlan_count--; | |
404 | ||
405 | vid_idx = (uint32_t)((vid >> E1000_VFTA_ENTRY_SHIFT) & | |
406 | E1000_VFTA_ENTRY_MASK); | |
407 | vid_bit = (uint32_t)(1 << (vid & E1000_VFTA_ENTRY_BIT_SHIFT_MASK)); | |
408 | vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, vid_idx); | |
409 | if (add) | |
410 | vfta |= vid_bit; | |
411 | else | |
412 | vfta &= ~vid_bit; | |
413 | ||
414 | E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, vid_idx, vfta); | |
415 | E1000_WRITE_FLUSH(hw); | |
416 | ||
417 | return 0; | |
418 | } | |
419 | ||
420 | static int | |
421 | igb_vf_set_rlpml(struct rte_eth_dev *dev, uint32_t vf, uint32_t *msgbuf) | |
422 | { | |
423 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
424 | uint16_t rlpml = msgbuf[1] & E1000_VMOLR_RLPML_MASK; | |
425 | uint32_t max_frame = rlpml + ETHER_HDR_LEN + ETHER_CRC_LEN; | |
426 | uint32_t vmolr; | |
427 | ||
428 | if ((max_frame < ETHER_MIN_LEN) || (max_frame > ETHER_MAX_JUMBO_FRAME_LEN)) | |
429 | return -1; | |
430 | ||
431 | vmolr = E1000_READ_REG(hw, E1000_VMOLR(vf)); | |
432 | ||
433 | vmolr &= ~E1000_VMOLR_RLPML_MASK; | |
434 | vmolr |= rlpml; | |
435 | ||
436 | /* Enable Long Packet support */ | |
437 | vmolr |= E1000_VMOLR_LPE; | |
438 | ||
439 | E1000_WRITE_REG(hw, E1000_VMOLR(vf), vmolr); | |
440 | E1000_WRITE_FLUSH(hw); | |
441 | ||
442 | return 0; | |
443 | } | |
444 | ||
445 | static int | |
446 | igb_rcv_msg_from_vf(struct rte_eth_dev *dev, uint16_t vf) | |
447 | { | |
448 | uint16_t mbx_size = E1000_VFMAILBOX_SIZE; | |
449 | uint32_t msgbuf[E1000_VFMAILBOX_SIZE]; | |
450 | int32_t retval; | |
451 | struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
452 | ||
453 | retval = e1000_read_mbx(hw, msgbuf, mbx_size, vf); | |
454 | if (retval) { | |
455 | PMD_INIT_LOG(ERR, "Error mbx recv msg from VF %d", vf); | |
456 | return retval; | |
457 | } | |
458 | ||
459 | /* do nothing with the message already processed */ | |
460 | if (msgbuf[0] & (E1000_VT_MSGTYPE_ACK | E1000_VT_MSGTYPE_NACK)) | |
461 | return retval; | |
462 | ||
463 | /* flush the ack before we write any messages back */ | |
464 | E1000_WRITE_FLUSH(hw); | |
465 | ||
466 | /* perform VF reset */ | |
467 | if (msgbuf[0] == E1000_VF_RESET) { | |
468 | return igb_vf_reset(dev, vf, msgbuf); | |
469 | } | |
470 | ||
471 | /* check & process VF to PF mailbox message */ | |
472 | switch ((msgbuf[0] & 0xFFFF)) { | |
473 | case E1000_VF_SET_MAC_ADDR: | |
474 | retval = igb_vf_set_mac_addr(dev, vf, msgbuf); | |
475 | break; | |
476 | case E1000_VF_SET_MULTICAST: | |
477 | retval = igb_vf_set_multicast(dev, vf, msgbuf); | |
478 | break; | |
479 | case E1000_VF_SET_LPE: | |
480 | retval = igb_vf_set_rlpml(dev, vf, msgbuf); | |
481 | break; | |
482 | case E1000_VF_SET_VLAN: | |
483 | retval = igb_vf_set_vlan(dev, vf, msgbuf); | |
484 | break; | |
485 | default: | |
486 | PMD_INIT_LOG(DEBUG, "Unhandled Msg %8.8x", | |
487 | (unsigned) msgbuf[0]); | |
488 | retval = E1000_ERR_MBX; | |
489 | break; | |
490 | } | |
491 | ||
492 | /* response the VF according to the message process result */ | |
493 | if (retval) | |
494 | msgbuf[0] |= E1000_VT_MSGTYPE_NACK; | |
495 | else | |
496 | msgbuf[0] |= E1000_VT_MSGTYPE_ACK; | |
497 | ||
498 | msgbuf[0] |= E1000_VT_MSGTYPE_CTS; | |
499 | ||
500 | e1000_write_mbx(hw, msgbuf, 1, vf); | |
501 | ||
502 | return retval; | |
503 | } | |
504 | ||
505 | static inline void | |
506 | igb_rcv_ack_from_vf(struct rte_eth_dev *dev, uint16_t vf) | |
507 | { | |
508 | uint32_t msg = E1000_VT_MSGTYPE_NACK; | |
509 | struct e1000_hw *hw = | |
510 | E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); | |
511 | ||
512 | e1000_write_mbx(hw, &msg, 1, vf); | |
513 | } | |
514 | ||
515 | void igb_pf_mbx_process(struct rte_eth_dev *eth_dev) | |
516 | { | |
517 | uint16_t vf; | |
518 | struct e1000_hw *hw = | |
519 | E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); | |
520 | ||
521 | for (vf = 0; vf < dev_num_vf(eth_dev); vf++) { | |
522 | /* check & process vf function level reset */ | |
523 | if (!e1000_check_for_rst(hw, vf)) | |
524 | igb_vf_reset_event(eth_dev, vf); | |
525 | ||
526 | /* check & process vf mailbox messages */ | |
527 | if (!e1000_check_for_msg(hw, vf)) | |
528 | igb_rcv_msg_from_vf(eth_dev, vf); | |
529 | ||
530 | /* check & process acks from vf */ | |
531 | if (!e1000_check_for_ack(hw, vf)) | |
532 | igb_rcv_ack_from_vf(eth_dev, vf); | |
533 | } | |
534 | } |