43eb0813d9f5ede55e461ed4ca42374a36798380
[dpdk.git] / drivers / net / fm10k / base / fm10k_vf.c
1 /*******************************************************************************
2
3 Copyright (c) 2013 - 2015, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9  1. Redistributions of source code must retain the above copyright notice,
10     this list of conditions and the following disclaimer.
11
12  2. Redistributions in binary form must reproduce the above copyright
13     notice, this list of conditions and the following disclaimer in the
14     documentation and/or other materials provided with the distribution.
15
16  3. Neither the name of the Intel Corporation nor the names of its
17     contributors may be used to endorse or promote products derived from
18     this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
31
32 ***************************************************************************/
33
34 #include "fm10k_vf.h"
35
36 /**
37  *  fm10k_stop_hw_vf - Stop Tx/Rx units
38  *  @hw: pointer to hardware structure
39  *
40  **/
41 STATIC s32 fm10k_stop_hw_vf(struct fm10k_hw *hw)
42 {
43         u8 *perm_addr = hw->mac.perm_addr;
44         u32 bal = 0, bah = 0, tdlen;
45         s32 err;
46         u16 i;
47
48         DEBUGFUNC("fm10k_stop_hw_vf");
49
50         /* we need to disable the queues before taking further steps */
51         err = fm10k_stop_hw_generic(hw);
52         if (err)
53                 return err;
54
55         /* If permanent address is set then we need to restore it */
56         if (FM10K_IS_VALID_ETHER_ADDR(perm_addr)) {
57                 bal = (((u32)perm_addr[3]) << 24) |
58                       (((u32)perm_addr[4]) << 16) |
59                       (((u32)perm_addr[5]) << 8);
60                 bah = (((u32)0xFF)         << 24) |
61                       (((u32)perm_addr[0]) << 16) |
62                       (((u32)perm_addr[1]) << 8) |
63                        ((u32)perm_addr[2]);
64         }
65
66         /* restore default itr_scale for next VF initialization */
67         tdlen = hw->mac.itr_scale << FM10K_TDLEN_ITR_SCALE_SHIFT;
68
69         /* The queues have already been disabled so we just need to
70          * update their base address registers
71          */
72         for (i = 0; i < hw->mac.max_queues; i++) {
73                 FM10K_WRITE_REG(hw, FM10K_TDBAL(i), bal);
74                 FM10K_WRITE_REG(hw, FM10K_TDBAH(i), bah);
75                 FM10K_WRITE_REG(hw, FM10K_RDBAL(i), bal);
76                 FM10K_WRITE_REG(hw, FM10K_RDBAH(i), bah);
77                 /* Restore ITR scale in software-defined mechanism in TDLEN
78                  * for next VF initialization. See definition of
79                  * FM10K_TDLEN_ITR_SCALE_SHIFT for more details on the use of
80                  * TDLEN here.
81                  */
82                 FM10K_WRITE_REG(hw, FM10K_TDLEN(i), tdlen);
83         }
84
85         return FM10K_SUCCESS;
86 }
87
88 /**
89  *  fm10k_reset_hw_vf - VF hardware reset
90  *  @hw: pointer to hardware structure
91  *
92  *  This function should return the hardware to a state similar to the
93  *  one it is in after just being initialized.
94  **/
95 STATIC s32 fm10k_reset_hw_vf(struct fm10k_hw *hw)
96 {
97         s32 err;
98
99         DEBUGFUNC("fm10k_reset_hw_vf");
100
101         /* shut down queues we own and reset DMA configuration */
102         err = fm10k_stop_hw_vf(hw);
103         if (err)
104                 return err;
105
106         /* Inititate VF reset */
107         FM10K_WRITE_REG(hw, FM10K_VFCTRL, FM10K_VFCTRL_RST);
108
109         /* Flush write and allow 100us for reset to complete */
110         FM10K_WRITE_FLUSH(hw);
111         usec_delay(FM10K_RESET_TIMEOUT);
112
113         /* Clear reset bit and verify it was cleared */
114         FM10K_WRITE_REG(hw, FM10K_VFCTRL, 0);
115         if (FM10K_READ_REG(hw, FM10K_VFCTRL) & FM10K_VFCTRL_RST)
116                 err = FM10K_ERR_RESET_FAILED;
117
118         return err;
119 }
120
121 /**
122  *  fm10k_init_hw_vf - VF hardware initialization
123  *  @hw: pointer to hardware structure
124  *
125  **/
126 STATIC s32 fm10k_init_hw_vf(struct fm10k_hw *hw)
127 {
128         u32 tqdloc, tqdloc0 = ~FM10K_READ_REG(hw, FM10K_TQDLOC(0));
129         s32 err;
130         u16 i;
131
132         DEBUGFUNC("fm10k_init_hw_vf");
133
134         /* verify we have at least 1 queue */
135         if (!~FM10K_READ_REG(hw, FM10K_TXQCTL(0)) ||
136             !~FM10K_READ_REG(hw, FM10K_RXQCTL(0))) {
137                 err = FM10K_ERR_NO_RESOURCES;
138                 goto reset_max_queues;
139         }
140
141         /* determine how many queues we have */
142         for (i = 1; tqdloc0 && (i < FM10K_MAX_QUEUES_POOL); i++) {
143                 /* verify the Descriptor cache offsets are increasing */
144                 tqdloc = ~FM10K_READ_REG(hw, FM10K_TQDLOC(i));
145                 if (!tqdloc || (tqdloc == tqdloc0))
146                         break;
147
148                 /* check to verify the PF doesn't own any of our queues */
149                 if (!~FM10K_READ_REG(hw, FM10K_TXQCTL(i)) ||
150                     !~FM10K_READ_REG(hw, FM10K_RXQCTL(i)))
151                         break;
152         }
153
154         /* shut down queues we own and reset DMA configuration */
155         err = fm10k_disable_queues_generic(hw, i);
156         if (err)
157                 goto reset_max_queues;
158
159         /* record maximum queue count */
160         hw->mac.max_queues = i;
161
162         /* fetch default VLAN and ITR scale */
163         hw->mac.default_vid = (FM10K_READ_REG(hw, FM10K_TXQCTL(0)) &
164                                FM10K_TXQCTL_VID_MASK) >> FM10K_TXQCTL_VID_SHIFT;
165         /* Read the ITR scale from TDLEN. See the definition of
166          * FM10K_TDLEN_ITR_SCALE_SHIFT for more information about how TDLEN is
167          * used here.
168          */
169         hw->mac.itr_scale = (FM10K_READ_REG(hw, FM10K_TDLEN(0)) &
170                              FM10K_TDLEN_ITR_SCALE_MASK) >>
171                             FM10K_TDLEN_ITR_SCALE_SHIFT;
172
173         return FM10K_SUCCESS;
174
175 reset_max_queues:
176         hw->mac.max_queues = 0;
177
178         return err;
179 }
180
181 /**
182  *  fm10k_is_slot_appropriate_vf - Indicate appropriate slot for this SKU
183  *  @hw: pointer to hardware structure
184  *
185  *  Looks at the PCIe bus info to confirm whether or not this slot can support
186  *  the necessary bandwidth for this device. Since the VF has no control over
187  *  the "slot" it is in, always indicate that the slot is appropriate.
188  **/
189 STATIC bool fm10k_is_slot_appropriate_vf(struct fm10k_hw *hw)
190 {
191         UNREFERENCED_1PARAMETER(hw);
192         DEBUGFUNC("fm10k_is_slot_appropriate_vf");
193
194         return TRUE;
195 }
196
197 /* This structure defines the attibutes to be parsed below */
198 const struct fm10k_tlv_attr fm10k_mac_vlan_msg_attr[] = {
199         FM10K_TLV_ATTR_U32(FM10K_MAC_VLAN_MSG_VLAN),
200         FM10K_TLV_ATTR_BOOL(FM10K_MAC_VLAN_MSG_SET),
201         FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_MAC),
202         FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_DEFAULT_MAC),
203         FM10K_TLV_ATTR_MAC_ADDR(FM10K_MAC_VLAN_MSG_MULTICAST),
204         FM10K_TLV_ATTR_LAST
205 };
206
207 /**
208  *  fm10k_update_vlan_vf - Update status of VLAN ID in VLAN filter table
209  *  @hw: pointer to hardware structure
210  *  @vid: VLAN ID to add to table
211  *  @vsi: Reserved, should always be 0
212  *  @set: Indicates if this is a set or clear operation
213  *
214  *  This function adds or removes the corresponding VLAN ID from the VLAN
215  *  filter table for this VF.
216  **/
217 STATIC s32 fm10k_update_vlan_vf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set)
218 {
219         struct fm10k_mbx_info *mbx = &hw->mbx;
220         u32 msg[4];
221
222         /* verify the index is not set */
223         if (vsi)
224                 return FM10K_ERR_PARAM;
225
226         /* verify upper 4 bits of vid and length are 0 */
227         if ((vid << 16 | vid) >> 28)
228                 return FM10K_ERR_PARAM;
229
230         /* encode set bit into the VLAN ID */
231         if (!set)
232                 vid |= FM10K_VLAN_CLEAR;
233
234         /* generate VLAN request */
235         fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN);
236         fm10k_tlv_attr_put_u32(msg, FM10K_MAC_VLAN_MSG_VLAN, vid);
237
238         /* load onto outgoing mailbox */
239         return mbx->ops.enqueue_tx(hw, mbx, msg);
240 }
241
242 /**
243  *  fm10k_msg_mac_vlan_vf - Read device MAC address from mailbox message
244  *  @hw: pointer to the HW structure
245  *  @results: Attributes for message
246  *  @mbx: unused mailbox data
247  *
248  *  This function should determine the MAC address for the VF
249  **/
250 s32 fm10k_msg_mac_vlan_vf(struct fm10k_hw *hw, u32 **results,
251                           struct fm10k_mbx_info *mbx)
252 {
253         u8 perm_addr[ETH_ALEN];
254         u16 vid;
255         s32 err;
256
257         UNREFERENCED_1PARAMETER(mbx);
258         DEBUGFUNC("fm10k_msg_mac_vlan_vf");
259
260         /* record MAC address requested */
261         err = fm10k_tlv_attr_get_mac_vlan(
262                                         results[FM10K_MAC_VLAN_MSG_DEFAULT_MAC],
263                                         perm_addr, &vid);
264         if (err)
265                 return err;
266
267         memcpy(hw->mac.perm_addr, perm_addr, ETH_ALEN);
268         hw->mac.default_vid = vid & (FM10K_VLAN_TABLE_VID_MAX - 1);
269         hw->mac.vlan_override = !!(vid & FM10K_VLAN_CLEAR);
270
271         return FM10K_SUCCESS;
272 }
273
274 /**
275  *  fm10k_read_mac_addr_vf - Read device MAC address
276  *  @hw: pointer to the HW structure
277  *
278  *  This function should determine the MAC address for the VF
279  **/
280 STATIC s32 fm10k_read_mac_addr_vf(struct fm10k_hw *hw)
281 {
282         u8 perm_addr[ETH_ALEN];
283         u32 base_addr;
284
285         DEBUGFUNC("fm10k_read_mac_addr_vf");
286
287         base_addr = FM10K_READ_REG(hw, FM10K_TDBAL(0));
288
289         /* last byte should be 0 */
290         if (base_addr << 24)
291                 return  FM10K_ERR_INVALID_MAC_ADDR;
292
293         perm_addr[3] = (u8)(base_addr >> 24);
294         perm_addr[4] = (u8)(base_addr >> 16);
295         perm_addr[5] = (u8)(base_addr >> 8);
296
297         base_addr = FM10K_READ_REG(hw, FM10K_TDBAH(0));
298
299         /* first byte should be all 1's */
300         if ((~base_addr) >> 24)
301                 return  FM10K_ERR_INVALID_MAC_ADDR;
302
303         perm_addr[0] = (u8)(base_addr >> 16);
304         perm_addr[1] = (u8)(base_addr >> 8);
305         perm_addr[2] = (u8)(base_addr);
306
307         memcpy(hw->mac.perm_addr, perm_addr, ETH_ALEN);
308         memcpy(hw->mac.addr, perm_addr, ETH_ALEN);
309
310         return FM10K_SUCCESS;
311 }
312
313 /**
314  *  fm10k_update_uc_addr_vf - Update device unicast addresses
315  *  @hw: pointer to the HW structure
316  *  @glort: unused
317  *  @mac: MAC address to add/remove from table
318  *  @vid: VLAN ID to add/remove from table
319  *  @add: Indicates if this is an add or remove operation
320  *  @flags: flags field to indicate add and secure - unused
321  *
322  *  This function is used to add or remove unicast MAC addresses for
323  *  the VF.
324  **/
325 STATIC s32 fm10k_update_uc_addr_vf(struct fm10k_hw *hw, u16 glort,
326                                    const u8 *mac, u16 vid, bool add, u8 flags)
327 {
328         struct fm10k_mbx_info *mbx = &hw->mbx;
329         u32 msg[7];
330
331         DEBUGFUNC("fm10k_update_uc_addr_vf");
332
333         UNREFERENCED_2PARAMETER(glort, flags);
334
335         /* verify VLAN ID is valid */
336         if (vid >= FM10K_VLAN_TABLE_VID_MAX)
337                 return FM10K_ERR_PARAM;
338
339         /* verify MAC address is valid */
340         if (!FM10K_IS_VALID_ETHER_ADDR(mac))
341                 return FM10K_ERR_PARAM;
342
343         /* verify we are not locked down on the MAC address */
344         if (FM10K_IS_VALID_ETHER_ADDR(hw->mac.perm_addr) &&
345             memcmp(hw->mac.perm_addr, mac, ETH_ALEN))
346                 return FM10K_ERR_PARAM;
347
348         /* add bit to notify us if this is a set or clear operation */
349         if (!add)
350                 vid |= FM10K_VLAN_CLEAR;
351
352         /* generate VLAN request */
353         fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN);
354         fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_MAC, mac, vid);
355
356         /* load onto outgoing mailbox */
357         return mbx->ops.enqueue_tx(hw, mbx, msg);
358 }
359
360 /**
361  *  fm10k_update_mc_addr_vf - Update device multicast addresses
362  *  @hw: pointer to the HW structure
363  *  @glort: unused
364  *  @mac: MAC address to add/remove from table
365  *  @vid: VLAN ID to add/remove from table
366  *  @add: Indicates if this is an add or remove operation
367  *
368  *  This function is used to add or remove multicast MAC addresses for
369  *  the VF.
370  **/
371 STATIC s32 fm10k_update_mc_addr_vf(struct fm10k_hw *hw, u16 glort,
372                                    const u8 *mac, u16 vid, bool add)
373 {
374         struct fm10k_mbx_info *mbx = &hw->mbx;
375         u32 msg[7];
376
377         DEBUGFUNC("fm10k_update_uc_addr_vf");
378
379         UNREFERENCED_1PARAMETER(glort);
380
381         /* verify VLAN ID is valid */
382         if (vid >= FM10K_VLAN_TABLE_VID_MAX)
383                 return FM10K_ERR_PARAM;
384
385         /* verify multicast address is valid */
386         if (!FM10K_IS_MULTICAST_ETHER_ADDR(mac))
387                 return FM10K_ERR_PARAM;
388
389         /* add bit to notify us if this is a set or clear operation */
390         if (!add)
391                 vid |= FM10K_VLAN_CLEAR;
392
393         /* generate VLAN request */
394         fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN);
395         fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_MULTICAST,
396                                     mac, vid);
397
398         /* load onto outgoing mailbox */
399         return mbx->ops.enqueue_tx(hw, mbx, msg);
400 }
401
402 /**
403  *  fm10k_update_int_moderator_vf - Request update of interrupt moderator list
404  *  @hw: pointer to hardware structure
405  *
406  *  This function will issue a request to the PF to rescan our MSI-X table
407  *  and to update the interrupt moderator linked list.
408  **/
409 STATIC void fm10k_update_int_moderator_vf(struct fm10k_hw *hw)
410 {
411         struct fm10k_mbx_info *mbx = &hw->mbx;
412         u32 msg[1];
413
414         /* generate MSI-X request */
415         fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MSIX);
416
417         /* load onto outgoing mailbox */
418         mbx->ops.enqueue_tx(hw, mbx, msg);
419 }
420
421 /* This structure defines the attibutes to be parsed below */
422 const struct fm10k_tlv_attr fm10k_lport_state_msg_attr[] = {
423         FM10K_TLV_ATTR_BOOL(FM10K_LPORT_STATE_MSG_DISABLE),
424         FM10K_TLV_ATTR_U8(FM10K_LPORT_STATE_MSG_XCAST_MODE),
425         FM10K_TLV_ATTR_BOOL(FM10K_LPORT_STATE_MSG_READY),
426         FM10K_TLV_ATTR_LAST
427 };
428
429 /**
430  *  fm10k_msg_lport_state_vf - Message handler for lport_state message from PF
431  *  @hw: Pointer to hardware structure
432  *  @results: pointer array containing parsed data
433  *  @mbx: Pointer to mailbox information structure
434  *
435  *  This handler is meant to capture the indication from the PF that we
436  *  are ready to bring up the interface.
437  **/
438 s32 fm10k_msg_lport_state_vf(struct fm10k_hw *hw, u32 **results,
439                              struct fm10k_mbx_info *mbx)
440 {
441         UNREFERENCED_1PARAMETER(mbx);
442         DEBUGFUNC("fm10k_msg_lport_state_vf");
443
444         hw->mac.dglort_map = !results[FM10K_LPORT_STATE_MSG_READY] ?
445                              FM10K_DGLORTMAP_NONE : FM10K_DGLORTMAP_ZERO;
446
447         return FM10K_SUCCESS;
448 }
449
450 /**
451  *  fm10k_update_lport_state_vf - Update device state in lower device
452  *  @hw: pointer to the HW structure
453  *  @glort: unused
454  *  @count: number of logical ports to enable - unused (always 1)
455  *  @enable: boolean value indicating if this is an enable or disable request
456  *
457  *  Notify the lower device of a state change.  If the lower device is
458  *  enabled we can add filters, if it is disabled all filters for this
459  *  logical port are flushed.
460  **/
461 STATIC s32 fm10k_update_lport_state_vf(struct fm10k_hw *hw, u16 glort,
462                                        u16 count, bool enable)
463 {
464         struct fm10k_mbx_info *mbx = &hw->mbx;
465         u32 msg[2];
466
467         UNREFERENCED_2PARAMETER(glort, count);
468         DEBUGFUNC("fm10k_update_lport_state_vf");
469
470         /* reset glort mask 0 as we have to wait to be enabled */
471         hw->mac.dglort_map = FM10K_DGLORTMAP_NONE;
472
473         /* generate port state request */
474         fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE);
475         if (!enable)
476                 fm10k_tlv_attr_put_bool(msg, FM10K_LPORT_STATE_MSG_DISABLE);
477
478         /* load onto outgoing mailbox */
479         return mbx->ops.enqueue_tx(hw, mbx, msg);
480 }
481
482 /**
483  *  fm10k_update_xcast_mode_vf - Request update of multicast mode
484  *  @hw: pointer to hardware structure
485  *  @glort: unused
486  *  @mode: integer value indicating mode being requested
487  *
488  *  This function will attempt to request a higher mode for the port
489  *  so that it can enable either multicast, multicast promiscuous, or
490  *  promiscuous mode of operation.
491  **/
492 STATIC s32 fm10k_update_xcast_mode_vf(struct fm10k_hw *hw, u16 glort, u8 mode)
493 {
494         struct fm10k_mbx_info *mbx = &hw->mbx;
495         u32 msg[3];
496
497         UNREFERENCED_1PARAMETER(glort);
498         DEBUGFUNC("fm10k_update_xcast_mode_vf");
499
500         if (mode > FM10K_XCAST_MODE_NONE)
501                 return FM10K_ERR_PARAM;
502
503         /* generate message requesting to change xcast mode */
504         fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE);
505         fm10k_tlv_attr_put_u8(msg, FM10K_LPORT_STATE_MSG_XCAST_MODE, mode);
506
507         /* load onto outgoing mailbox */
508         return mbx->ops.enqueue_tx(hw, mbx, msg);
509 }
510
511 const struct fm10k_tlv_attr fm10k_1588_msg_attr[] = {
512         FM10K_TLV_ATTR_U64(FM10K_1588_MSG_CLK_OFFSET),
513         FM10K_TLV_ATTR_LAST
514 };
515
516 /* currently there is no shared 1588 message handler */
517
518 /**
519  *  fm10k_update_hw_stats_vf - Updates hardware related statistics of VF
520  *  @hw: pointer to hardware structure
521  *  @stats: pointer to statistics structure
522  *
523  *  This function collects and aggregates per queue hardware statistics.
524  **/
525 STATIC void fm10k_update_hw_stats_vf(struct fm10k_hw *hw,
526                                      struct fm10k_hw_stats *stats)
527 {
528         DEBUGFUNC("fm10k_update_hw_stats_vf");
529
530         fm10k_update_hw_stats_q(hw, stats->q, 0, hw->mac.max_queues);
531 }
532
533 /**
534  *  fm10k_rebind_hw_stats_vf - Resets base for hardware statistics of VF
535  *  @hw: pointer to hardware structure
536  *  @stats: pointer to the stats structure to update
537  *
538  *  This function resets the base for queue hardware statistics.
539  **/
540 STATIC void fm10k_rebind_hw_stats_vf(struct fm10k_hw *hw,
541                                      struct fm10k_hw_stats *stats)
542 {
543         DEBUGFUNC("fm10k_rebind_hw_stats_vf");
544
545         /* Unbind Queue Statistics */
546         fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues);
547
548         /* Reinitialize bases for all stats */
549         fm10k_update_hw_stats_vf(hw, stats);
550 }
551
552 /**
553  *  fm10k_configure_dglort_map_vf - Configures GLORT entry and queues
554  *  @hw: pointer to hardware structure
555  *  @dglort: pointer to dglort configuration structure
556  *
557  *  Reads the configuration structure contained in dglort_cfg and uses
558  *  that information to then populate a DGLORTMAP/DEC entry and the queues
559  *  to which it has been assigned.
560  **/
561 STATIC s32 fm10k_configure_dglort_map_vf(struct fm10k_hw *hw,
562                                          struct fm10k_dglort_cfg *dglort)
563 {
564         UNREFERENCED_1PARAMETER(hw);
565         DEBUGFUNC("fm10k_configure_dglort_map_vf");
566
567         /* verify the dglort pointer */
568         if (!dglort)
569                 return FM10K_ERR_PARAM;
570
571         /* stub for now until we determine correct message for this */
572
573         return FM10K_SUCCESS;
574 }
575
576 /**
577  *  fm10k_adjust_systime_vf - Adjust systime frequency
578  *  @hw: pointer to hardware structure
579  *  @ppb: adjustment rate in parts per billion
580  *
581  *  This function takes an adjustment rate in parts per billion and will
582  *  verify that this value is 0 as the VF cannot support adjusting the
583  *  systime clock.
584  *
585  *  If the ppb value is non-zero the return is ERR_PARAM else success
586  **/
587 STATIC s32 fm10k_adjust_systime_vf(struct fm10k_hw *hw, s32 ppb)
588 {
589         UNREFERENCED_1PARAMETER(hw);
590         DEBUGFUNC("fm10k_adjust_systime_vf");
591
592         /* The VF cannot adjust the clock frequency, however it should
593          * already have a syntonic clock with whichever host interface is
594          * running as the master for the host interface clock domain so
595          * there should be not frequency adjustment necessary.
596          */
597         return ppb ? FM10K_ERR_PARAM : FM10K_SUCCESS;
598 }
599
600 /**
601  *  fm10k_read_systime_vf - Reads value of systime registers
602  *  @hw: pointer to the hardware structure
603  *
604  *  Function reads the content of 2 registers, combined to represent a 64 bit
605  *  value measured in nanoseconds.  In order to guarantee the value is accurate
606  *  we check the 32 most significant bits both before and after reading the
607  *  32 least significant bits to verify they didn't change as we were reading
608  *  the registers.
609  **/
610 static u64 fm10k_read_systime_vf(struct fm10k_hw *hw)
611 {
612         u32 systime_l, systime_h, systime_tmp;
613
614         systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
615
616         do {
617                 systime_tmp = systime_h;
618                 systime_l = fm10k_read_reg(hw, FM10K_VFSYSTIME);
619                 systime_h = fm10k_read_reg(hw, FM10K_VFSYSTIME + 1);
620         } while (systime_tmp != systime_h);
621
622         return ((u64)systime_h << 32) | systime_l;
623 }
624
625 static const struct fm10k_msg_data fm10k_msg_data_vf[] = {
626         FM10K_TLV_MSG_TEST_HANDLER(fm10k_tlv_msg_test),
627         FM10K_VF_MSG_MAC_VLAN_HANDLER(fm10k_msg_mac_vlan_vf),
628         FM10K_VF_MSG_LPORT_STATE_HANDLER(fm10k_msg_lport_state_vf),
629         FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error),
630 };
631
632 /**
633  *  fm10k_init_ops_vf - Inits func ptrs and MAC type
634  *  @hw: pointer to hardware structure
635  *
636  *  Initialize the function pointers and assign the MAC type for VF.
637  *  Does not touch the hardware.
638  **/
639 s32 fm10k_init_ops_vf(struct fm10k_hw *hw)
640 {
641         struct fm10k_mac_info *mac = &hw->mac;
642
643         DEBUGFUNC("fm10k_init_ops_vf");
644
645         fm10k_init_ops_generic(hw);
646
647         mac->ops.reset_hw = &fm10k_reset_hw_vf;
648         mac->ops.init_hw = &fm10k_init_hw_vf;
649         mac->ops.start_hw = &fm10k_start_hw_generic;
650         mac->ops.stop_hw = &fm10k_stop_hw_vf;
651         mac->ops.is_slot_appropriate = &fm10k_is_slot_appropriate_vf;
652         mac->ops.update_vlan = &fm10k_update_vlan_vf;
653         mac->ops.read_mac_addr = &fm10k_read_mac_addr_vf;
654         mac->ops.update_uc_addr = &fm10k_update_uc_addr_vf;
655         mac->ops.update_mc_addr = &fm10k_update_mc_addr_vf;
656         mac->ops.update_xcast_mode = &fm10k_update_xcast_mode_vf;
657         mac->ops.update_int_moderator = &fm10k_update_int_moderator_vf;
658         mac->ops.update_lport_state = &fm10k_update_lport_state_vf;
659         mac->ops.update_hw_stats = &fm10k_update_hw_stats_vf;
660         mac->ops.rebind_hw_stats = &fm10k_rebind_hw_stats_vf;
661         mac->ops.configure_dglort_map = &fm10k_configure_dglort_map_vf;
662         mac->ops.get_host_state = &fm10k_get_host_state_generic;
663         mac->ops.adjust_systime = &fm10k_adjust_systime_vf;
664         mac->ops.read_systime = &fm10k_read_systime_vf;
665
666         mac->max_msix_vectors = fm10k_get_pcie_msix_count_generic(hw);
667
668         return fm10k_pfvf_mbx_init(hw, &hw->mbx, fm10k_msg_data_vf, 0);
669 }