1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2013 - 2019 Intel Corporation. */ |
3 | |
4 | #include "fm10k_vf.h" |
5 | |
6 | /** |
7 | * fm10k_stop_hw_vf - Stop Tx/Rx units |
8 | * @hw: pointer to hardware structure |
9 | * |
10 | **/ |
11 | static s32 fm10k_stop_hw_vf(struct fm10k_hw *hw) |
12 | { |
13 | u8 *perm_addr = hw->mac.perm_addr; |
14 | u32 bal = 0, bah = 0, tdlen; |
15 | s32 err; |
16 | u16 i; |
17 | |
18 | /* we need to disable the queues before taking further steps */ |
19 | err = fm10k_stop_hw_generic(hw); |
20 | if (err && err != FM10K_ERR_REQUESTS_PENDING) |
21 | return err; |
22 | |
23 | /* If permanent address is set then we need to restore it */ |
24 | if (is_valid_ether_addr(addr: perm_addr)) { |
25 | bal = (((u32)perm_addr[3]) << 24) | |
26 | (((u32)perm_addr[4]) << 16) | |
27 | (((u32)perm_addr[5]) << 8); |
28 | bah = (((u32)0xFF) << 24) | |
29 | (((u32)perm_addr[0]) << 16) | |
30 | (((u32)perm_addr[1]) << 8) | |
31 | ((u32)perm_addr[2]); |
32 | } |
33 | |
34 | /* restore default itr_scale for next VF initialization */ |
35 | tdlen = hw->mac.itr_scale << FM10K_TDLEN_ITR_SCALE_SHIFT; |
36 | |
37 | /* The queues have already been disabled so we just need to |
38 | * update their base address registers |
39 | */ |
40 | for (i = 0; i < hw->mac.max_queues; i++) { |
41 | fm10k_write_reg(hw, FM10K_TDBAL(i), bal); |
42 | fm10k_write_reg(hw, FM10K_TDBAH(i), bah); |
43 | fm10k_write_reg(hw, FM10K_RDBAL(i), bal); |
44 | fm10k_write_reg(hw, FM10K_RDBAH(i), bah); |
45 | /* Restore ITR scale in software-defined mechanism in TDLEN |
46 | * for next VF initialization. See definition of |
47 | * FM10K_TDLEN_ITR_SCALE_SHIFT for more details on the use of |
48 | * TDLEN here. |
49 | */ |
50 | fm10k_write_reg(hw, FM10K_TDLEN(i), tdlen); |
51 | } |
52 | |
53 | return err; |
54 | } |
55 | |
56 | /** |
57 | * fm10k_reset_hw_vf - VF hardware reset |
58 | * @hw: pointer to hardware structure |
59 | * |
60 | * This function should return the hardware to a state similar to the |
61 | * one it is in after just being initialized. |
62 | **/ |
63 | static s32 fm10k_reset_hw_vf(struct fm10k_hw *hw) |
64 | { |
65 | s32 err; |
66 | |
67 | /* shut down queues we own and reset DMA configuration */ |
68 | err = fm10k_stop_hw_vf(hw); |
69 | if (err == FM10K_ERR_REQUESTS_PENDING) |
70 | hw->mac.reset_while_pending++; |
71 | else if (err) |
72 | return err; |
73 | |
74 | /* Inititate VF reset */ |
75 | fm10k_write_reg(hw, FM10K_VFCTRL, FM10K_VFCTRL_RST); |
76 | |
77 | /* Flush write and allow 100us for reset to complete */ |
78 | fm10k_write_flush(hw); |
79 | udelay(FM10K_RESET_TIMEOUT); |
80 | |
81 | /* Clear reset bit and verify it was cleared */ |
82 | fm10k_write_reg(hw, FM10K_VFCTRL, 0); |
83 | if (fm10k_read_reg(hw, FM10K_VFCTRL) & FM10K_VFCTRL_RST) |
84 | return FM10K_ERR_RESET_FAILED; |
85 | |
86 | return 0; |
87 | } |
88 | |
89 | /** |
90 | * fm10k_init_hw_vf - VF hardware initialization |
91 | * @hw: pointer to hardware structure |
92 | * |
93 | **/ |
94 | static s32 fm10k_init_hw_vf(struct fm10k_hw *hw) |
95 | { |
96 | u32 tqdloc, tqdloc0 = ~fm10k_read_reg(hw, FM10K_TQDLOC(0)); |
97 | s32 err; |
98 | u16 i; |
99 | |
100 | /* verify we have at least 1 queue */ |
101 | if (!~fm10k_read_reg(hw, FM10K_TXQCTL(0)) || |
102 | !~fm10k_read_reg(hw, FM10K_RXQCTL(0))) { |
103 | err = FM10K_ERR_NO_RESOURCES; |
104 | goto reset_max_queues; |
105 | } |
106 | |
107 | /* determine how many queues we have */ |
108 | for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) { |
109 | /* verify the Descriptor cache offsets are increasing */ |
110 | tqdloc = ~fm10k_read_reg(hw, FM10K_TQDLOC(i)); |
111 | if (!tqdloc || (tqdloc == tqdloc0)) |
112 | break; |
113 | |
114 | /* check to verify the PF doesn't own any of our queues */ |
115 | if (!~fm10k_read_reg(hw, FM10K_TXQCTL(i)) || |
116 | !~fm10k_read_reg(hw, FM10K_RXQCTL(i))) |
117 | break; |
118 | } |
119 | |
120 | /* shut down queues we own and reset DMA configuration */ |
121 | err = fm10k_disable_queues_generic(hw, q_cnt: i); |
122 | if (err) |
123 | goto reset_max_queues; |
124 | |
125 | /* record maximum queue count */ |
126 | hw->mac.max_queues = i; |
127 | |
128 | /* fetch default VLAN and ITR scale */ |
129 | hw->mac.default_vid = (fm10k_read_reg(hw, FM10K_TXQCTL(0)) & |
130 | FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT; |
131 | /* Read the ITR scale from TDLEN. See the definition of |
132 | * FM10K_TDLEN_ITR_SCALE_SHIFT for more information about how TDLEN is |
133 | * used here. |
134 | */ |
135 | hw->mac.itr_scale = (fm10k_read_reg(hw, FM10K_TDLEN(0)) & |
136 | FM10K_TDLEN_ITR_SCALE_MASK) >> |
137 | FM10K_TDLEN_ITR_SCALE_SHIFT; |
138 | |
139 | return 0; |
140 | |
141 | reset_max_queues: |
142 | hw->mac.max_queues = 0; |
143 | |
144 | return err; |
145 | } |
146 | |
147 | /* This structure defines the attibutes to be parsed below */ |
148 | const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[] = { |
149 | FM10K_TLV_ATTR_U32(FM10K_MAC_VLAN_MSG_VLAN), |
150 | FM10K_TLV_ATTR_BOOL(FM10K_MAC_VLAN_MSG_SET), |
151 | FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_MAC), |
152 | FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_DEFAULT_MAC), |
153 | FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_MULTICAST), |
154 | FM10K_TLV_ATTR_LAST |
155 | }; |
156 | |
157 | /** |
158 | * fm10k_update_vlan_vf - Update status of VLAN ID in VLAN filter table |
159 | * @hw: pointer to hardware structure |
160 | * @vid: VLAN ID to add to table |
161 | * @vsi: Reserved, should always be 0 |
162 | * @set: Indicates if this is a set or clear operation |
163 | * |
164 | * This function adds or removes the corresponding VLAN ID from the VLAN |
165 | * filter table for this VF. |
166 | **/ |
167 | static s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) |
168 | { |
169 | struct fm10k_mbx_info *mbx = &hw->mbx; |
170 | u32 msg[4]; |
171 | |
172 | /* verify the index is not set */ |
173 | if (vsi) |
174 | return FM10K_ERR_PARAM; |
175 | |
176 | /* clever trick to verify reserved bits in both vid and length */ |
177 | if ((vid << 16 | vid) >> 28) |
178 | return FM10K_ERR_PARAM; |
179 | |
180 | /* encode set bit into the VLAN ID */ |
181 | if (!set) |
182 | vid |= FM10K_VLAN_CLEAR; |
183 | |
184 | /* generate VLAN request */ |
185 | fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); |
186 | fm10k_tlv_attr_put_u32(msg, FM10K_MAC_VLAN_MSG_VLAN, vid); |
187 | |
188 | /* load onto outgoing mailbox */ |
189 | return mbx->ops.enqueue_tx(hw, mbx, msg); |
190 | } |
191 | |
192 | /** |
193 | * fm10k_msg_mac_vlan_vf - Read device MAC address from mailbox message |
194 | * @hw: pointer to the HW structure |
195 | * @results: Attributes for message |
196 | * @mbx: unused mailbox data |
197 | * |
198 | * This function should determine the MAC address for the VF |
199 | **/ |
200 | s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results, |
201 | struct fm10k_mbx_info __always_unused *mbx) |
202 | { |
203 | u8 perm_addr[ETH_ALEN]; |
204 | u16 vid; |
205 | s32 err; |
206 | |
207 | /* record MAC address requested */ |
208 | err = fm10k_tlv_attr_get_mac_vlan( |
209 | results[FM10K_MAC_VLAN_MSG_DEFAULT_MAC], |
210 | perm_addr, &vid); |
211 | if (err) |
212 | return err; |
213 | |
214 | ether_addr_copy(dst: hw->mac.perm_addr, src: perm_addr); |
215 | hw->mac.default_vid = vid & (FM10K_VLAN_TABLE_VID_MAX - 1); |
216 | hw->mac.vlan_override = !!(vid & FM10K_VLAN_OVERRIDE); |
217 | |
218 | return 0; |
219 | } |
220 | |
221 | /** |
222 | * fm10k_read_mac_addr_vf - Read device MAC address |
223 | * @hw: pointer to the HW structure |
224 | * |
225 | * This function should determine the MAC address for the VF |
226 | **/ |
227 | static s32 fm10k_read_mac_addr_vf(struct fm10k_hw *hw) |
228 | { |
229 | u8 perm_addr[ETH_ALEN]; |
230 | u32 base_addr; |
231 | |
232 | base_addr = fm10k_read_reg(hw, FM10K_TDBAL(0)); |
233 | |
234 | /* last byte should be 0 */ |
235 | if (base_addr << 24) |
236 | return FM10K_ERR_INVALID_MAC_ADDR; |
237 | |
238 | perm_addr[3] = (u8)(base_addr >> 24); |
239 | perm_addr[4] = (u8)(base_addr >> 16); |
240 | perm_addr[5] = (u8)(base_addr >> 8); |
241 | |
242 | base_addr = fm10k_read_reg(hw, FM10K_TDBAH(0)); |
243 | |
244 | /* first byte should be all 1's */ |
245 | if ((~base_addr) >> 24) |
246 | return FM10K_ERR_INVALID_MAC_ADDR; |
247 | |
248 | perm_addr[0] = (u8)(base_addr >> 16); |
249 | perm_addr[1] = (u8)(base_addr >> 8); |
250 | perm_addr[2] = (u8)(base_addr); |
251 | |
252 | ether_addr_copy(dst: hw->mac.perm_addr, src: perm_addr); |
253 | ether_addr_copy(dst: hw->mac.addr, src: perm_addr); |
254 | |
255 | return 0; |
256 | } |
257 | |
258 | /** |
259 | * fm10k_update_uc_addr_vf - Update device unicast addresses |
260 | * @hw: pointer to the HW structure |
261 | * @glort: unused |
262 | * @mac: MAC address to add/remove from table |
263 | * @vid: VLAN ID to add/remove from table |
264 | * @add: Indicates if this is an add or remove operation |
265 | * @flags: flags field to indicate add and secure - unused |
266 | * |
267 | * This function is used to add or remove unicast MAC addresses for |
268 | * the VF. |
269 | **/ |
270 | static s32 fm10k_update_uc_addr_vf(struct fm10k_hw *hw, |
271 | u16 __always_unused glort, |
272 | const u8 *mac, u16 vid, bool add, |
273 | u8 __always_unused flags) |
274 | { |
275 | struct fm10k_mbx_info *mbx = &hw->mbx; |
276 | u32 msg[7]; |
277 | |
278 | /* verify VLAN ID is valid */ |
279 | if (vid >= FM10K_VLAN_TABLE_VID_MAX) |
280 | return FM10K_ERR_PARAM; |
281 | |
282 | /* verify MAC address is valid */ |
283 | if (!is_valid_ether_addr(addr: mac)) |
284 | return FM10K_ERR_PARAM; |
285 | |
286 | /* verify we are not locked down on the MAC address */ |
287 | if (is_valid_ether_addr(addr: hw->mac.perm_addr) && |
288 | !ether_addr_equal(addr1: hw->mac.perm_addr, addr2: mac)) |
289 | return FM10K_ERR_PARAM; |
290 | |
291 | /* add bit to notify us if this is a set or clear operation */ |
292 | if (!add) |
293 | vid |= FM10K_VLAN_CLEAR; |
294 | |
295 | /* generate VLAN request */ |
296 | fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); |
297 | fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_MAC, mac, vid); |
298 | |
299 | /* load onto outgoing mailbox */ |
300 | return mbx->ops.enqueue_tx(hw, mbx, msg); |
301 | } |
302 | |
303 | /** |
304 | * fm10k_update_mc_addr_vf - Update device multicast addresses |
305 | * @hw: pointer to the HW structure |
306 | * @glort: unused |
307 | * @mac: MAC address to add/remove from table |
308 | * @vid: VLAN ID to add/remove from table |
309 | * @add: Indicates if this is an add or remove operation |
310 | * |
311 | * This function is used to add or remove multicast MAC addresses for |
312 | * the VF. |
313 | **/ |
314 | static s32 fm10k_update_mc_addr_vf(struct fm10k_hw *hw, |
315 | u16 __always_unused glort, |
316 | const u8 *mac, u16 vid, bool add) |
317 | { |
318 | struct fm10k_mbx_info *mbx = &hw->mbx; |
319 | u32 msg[7]; |
320 | |
321 | /* verify VLAN ID is valid */ |
322 | if (vid >= FM10K_VLAN_TABLE_VID_MAX) |
323 | return FM10K_ERR_PARAM; |
324 | |
325 | /* verify multicast address is valid */ |
326 | if (!is_multicast_ether_addr(addr: mac)) |
327 | return FM10K_ERR_PARAM; |
328 | |
329 | /* add bit to notify us if this is a set or clear operation */ |
330 | if (!add) |
331 | vid |= FM10K_VLAN_CLEAR; |
332 | |
333 | /* generate VLAN request */ |
334 | fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); |
335 | fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_MULTICAST, |
336 | mac, vid); |
337 | |
338 | /* load onto outgoing mailbox */ |
339 | return mbx->ops.enqueue_tx(hw, mbx, msg); |
340 | } |
341 | |
342 | /** |
343 | * fm10k_update_int_moderator_vf - Request update of interrupt moderator list |
344 | * @hw: pointer to hardware structure |
345 | * |
346 | * This function will issue a request to the PF to rescan our MSI-X table |
347 | * and to update the interrupt moderator linked list. |
348 | **/ |
349 | static void fm10k_update_int_moderator_vf(struct fm10k_hw *hw) |
350 | { |
351 | struct fm10k_mbx_info *mbx = &hw->mbx; |
352 | u32 msg[1]; |
353 | |
354 | /* generate MSI-X request */ |
355 | fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MSIX); |
356 | |
357 | /* load onto outgoing mailbox */ |
358 | mbx->ops.enqueue_tx(hw, mbx, msg); |
359 | } |
360 | |
361 | /* This structure defines the attibutes to be parsed below */ |
362 | const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[] = { |
363 | FM10K_TLV_ATTR_BOOL(FM10K_LPORT_STATE_MSG_DISABLE), |
364 | FM10K_TLV_ATTR_U8(FM10K_LPORT_STATE_MSG_XCAST_MODE), |
365 | FM10K_TLV_ATTR_BOOL(FM10K_LPORT_STATE_MSG_READY), |
366 | FM10K_TLV_ATTR_LAST |
367 | }; |
368 | |
369 | /** |
370 | * fm10k_msg_lport_state_vf - Message handler for lport_state message from PF |
371 | * @hw: Pointer to hardware structure |
372 | * @results: pointer array containing parsed data |
373 | * @mbx: Pointer to mailbox information structure |
374 | * |
375 | * This handler is meant to capture the indication from the PF that we |
376 | * are ready to bring up the interface. |
377 | **/ |
378 | s32 fm10k_msg_lport_state_vf(struct fm10k_hw *hw, u32 **results, |
379 | struct fm10k_mbx_info __always_unused *mbx) |
380 | { |
381 | hw->mac.dglort_map = !results[FM10K_LPORT_STATE_MSG_READY] ? |
382 | FM10K_DGLORTMAP_NONE : FM10K_DGLORTMAP_ZERO; |
383 | |
384 | return 0; |
385 | } |
386 | |
387 | /** |
388 | * fm10k_update_lport_state_vf - Update device state in lower device |
389 | * @hw: pointer to the HW structure |
390 | * @glort: unused |
391 | * @count: number of logical ports to enable - unused (always 1) |
392 | * @enable: boolean value indicating if this is an enable or disable request |
393 | * |
394 | * Notify the lower device of a state change. If the lower device is |
395 | * enabled we can add filters, if it is disabled all filters for this |
396 | * logical port are flushed. |
397 | **/ |
398 | static s32 fm10k_update_lport_state_vf(struct fm10k_hw *hw, |
399 | u16 __always_unused glort, |
400 | u16 __always_unused count, bool enable) |
401 | { |
402 | struct fm10k_mbx_info *mbx = &hw->mbx; |
403 | u32 msg[2]; |
404 | |
405 | /* reset glort mask 0 as we have to wait to be enabled */ |
406 | hw->mac.dglort_map = FM10K_DGLORTMAP_NONE; |
407 | |
408 | /* generate port state request */ |
409 | fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); |
410 | if (!enable) |
411 | fm10k_tlv_attr_put_bool(msg, FM10K_LPORT_STATE_MSG_DISABLE); |
412 | |
413 | /* load onto outgoing mailbox */ |
414 | return mbx->ops.enqueue_tx(hw, mbx, msg); |
415 | } |
416 | |
417 | /** |
418 | * fm10k_update_xcast_mode_vf - Request update of multicast mode |
419 | * @hw: pointer to hardware structure |
420 | * @glort: unused |
421 | * @mode: integer value indicating mode being requested |
422 | * |
423 | * This function will attempt to request a higher mode for the port |
424 | * so that it can enable either multicast, multicast promiscuous, or |
425 | * promiscuous mode of operation. |
426 | **/ |
427 | static s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, |
428 | u16 __always_unused glort, u8 mode) |
429 | { |
430 | struct fm10k_mbx_info *mbx = &hw->mbx; |
431 | u32 msg[3]; |
432 | |
433 | if (mode > FM10K_XCAST_MODE_NONE) |
434 | return FM10K_ERR_PARAM; |
435 | |
436 | /* generate message requesting to change xcast mode */ |
437 | fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); |
438 | fm10k_tlv_attr_put_u8(msg, FM10K_LPORT_STATE_MSG_XCAST_MODE, mode); |
439 | |
440 | /* load onto outgoing mailbox */ |
441 | return mbx->ops.enqueue_tx(hw, mbx, msg); |
442 | } |
443 | |
444 | /** |
445 | * fm10k_update_hw_stats_vf - Updates hardware related statistics of VF |
446 | * @hw: pointer to hardware structure |
447 | * @stats: pointer to statistics structure |
448 | * |
449 | * This function collects and aggregates per queue hardware statistics. |
450 | **/ |
451 | static void fm10k_update_hw_stats_vf(struct fm10k_hw *hw, |
452 | struct fm10k_hw_stats *stats) |
453 | { |
454 | fm10k_update_hw_stats_q(hw, q: stats->q, idx: 0, count: hw->mac.max_queues); |
455 | } |
456 | |
457 | /** |
458 | * fm10k_rebind_hw_stats_vf - Resets base for hardware statistics of VF |
459 | * @hw: pointer to hardware structure |
460 | * @stats: pointer to the stats structure to update |
461 | * |
462 | * This function resets the base for queue hardware statistics. |
463 | **/ |
464 | static void fm10k_rebind_hw_stats_vf(struct fm10k_hw *hw, |
465 | struct fm10k_hw_stats *stats) |
466 | { |
467 | /* Unbind Queue Statistics */ |
468 | fm10k_unbind_hw_stats_q(q: stats->q, idx: 0, count: hw->mac.max_queues); |
469 | |
470 | /* Reinitialize bases for all stats */ |
471 | fm10k_update_hw_stats_vf(hw, stats); |
472 | } |
473 | |
474 | /** |
475 | * fm10k_configure_dglort_map_vf - Configures GLORT entry and queues |
476 | * @hw: pointer to hardware structure |
477 | * @dglort: pointer to dglort configuration structure |
478 | * |
479 | * Reads the configuration structure contained in dglort_cfg and uses |
480 | * that information to then populate a DGLORTMAP/DEC entry and the queues |
481 | * to which it has been assigned. |
482 | **/ |
483 | static s32 fm10k_configure_dglort_map_vf(struct fm10k_hw __always_unused *hw, |
484 | struct fm10k_dglort_cfg *dglort) |
485 | { |
486 | /* verify the dglort pointer */ |
487 | if (!dglort) |
488 | return FM10K_ERR_PARAM; |
489 | |
490 | /* stub for now until we determine correct message for this */ |
491 | |
492 | return 0; |
493 | } |
494 | |
495 | static const struct fm10k_msg_data fm10k_msg_data_vf[] = { |
496 | FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test), |
497 | FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf), |
498 | FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf), |
499 | FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), |
500 | }; |
501 | |
502 | static const struct fm10k_mac_ops mac_ops_vf = { |
503 | .get_bus_info = fm10k_get_bus_info_generic, |
504 | .reset_hw = fm10k_reset_hw_vf, |
505 | .init_hw = fm10k_init_hw_vf, |
506 | .start_hw = fm10k_start_hw_generic, |
507 | .stop_hw = fm10k_stop_hw_vf, |
508 | .update_vlan = fm10k_update_vlan_vf, |
509 | .read_mac_addr = fm10k_read_mac_addr_vf, |
510 | .update_uc_addr = fm10k_update_uc_addr_vf, |
511 | .update_mc_addr = fm10k_update_mc_addr_vf, |
512 | .update_xcast_mode = fm10k_update_xcast_mode_vf, |
513 | .update_int_moderator = fm10k_update_int_moderator_vf, |
514 | .update_lport_state = fm10k_update_lport_state_vf, |
515 | .update_hw_stats = fm10k_update_hw_stats_vf, |
516 | .rebind_hw_stats = fm10k_rebind_hw_stats_vf, |
517 | .configure_dglort_map = fm10k_configure_dglort_map_vf, |
518 | .get_host_state = fm10k_get_host_state_generic, |
519 | }; |
520 | |
521 | static s32 fm10k_get_invariants_vf(struct fm10k_hw *hw) |
522 | { |
523 | fm10k_get_invariants_generic(hw); |
524 | |
525 | return fm10k_pfvf_mbx_init(hw, &hw->mbx, fm10k_msg_data_vf, 0); |
526 | } |
527 | |
528 | const struct fm10k_info fm10k_vf_info = { |
529 | .mac = fm10k_mac_vf, |
530 | .get_invariants = fm10k_get_invariants_vf, |
531 | .mac_ops = &mac_ops_vf, |
532 | }; |
533 | |