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