@@ -558,11 +558,16 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter)
558
558
static void igc_ptp_clear_tx_tstamp (struct igc_adapter * adapter )
559
559
{
560
560
unsigned long flags ;
561
+ int i ;
561
562
562
563
spin_lock_irqsave (& adapter -> ptp_tx_lock , flags );
563
564
564
- dev_kfree_skb_any (adapter -> ptp_tx_skb );
565
- adapter -> ptp_tx_skb = NULL ;
565
+ for (i = 0 ; i < IGC_MAX_TX_TSTAMP_REGS ; i ++ ) {
566
+ struct igc_tx_timestamp_request * tstamp = & adapter -> tx_tstamp [i ];
567
+
568
+ dev_kfree_skb_any (tstamp -> skb );
569
+ tstamp -> skb = NULL ;
570
+ }
566
571
567
572
spin_unlock_irqrestore (& adapter -> ptp_tx_lock , flags );
568
573
}
@@ -659,61 +664,106 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,
659
664
}
660
665
661
666
/* Requires adapter->ptp_tx_lock held by caller. */
662
- static void igc_ptp_tx_timeout (struct igc_adapter * adapter )
667
+ static void igc_ptp_tx_timeout (struct igc_adapter * adapter ,
668
+ struct igc_tx_timestamp_request * tstamp )
663
669
{
664
- struct igc_hw * hw = & adapter -> hw ;
665
-
666
- dev_kfree_skb_any (adapter -> ptp_tx_skb );
667
- adapter -> ptp_tx_skb = NULL ;
670
+ dev_kfree_skb_any (tstamp -> skb );
671
+ tstamp -> skb = NULL ;
668
672
adapter -> tx_hwtstamp_timeouts ++ ;
669
- /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
670
- rd32 (IGC_TXSTMPH );
673
+
671
674
netdev_warn (adapter -> netdev , "Tx timestamp timeout\n" );
672
675
}
673
676
674
677
void igc_ptp_tx_hang (struct igc_adapter * adapter )
675
678
{
679
+ struct igc_tx_timestamp_request * tstamp ;
680
+ struct igc_hw * hw = & adapter -> hw ;
676
681
unsigned long flags ;
682
+ bool found = false;
683
+ int i ;
677
684
678
685
spin_lock_irqsave (& adapter -> ptp_tx_lock , flags );
679
686
680
- if (!adapter -> ptp_tx_skb )
681
- goto unlock ;
687
+ for (i = 0 ; i < IGC_MAX_TX_TSTAMP_REGS ; i ++ ) {
688
+ tstamp = & adapter -> tx_tstamp [i ];
689
+
690
+ if (!tstamp -> skb )
691
+ continue ;
682
692
683
- if (time_is_after_jiffies (adapter -> ptp_tx_start + IGC_PTP_TX_TIMEOUT ))
684
- goto unlock ;
693
+ if (time_is_after_jiffies (tstamp -> start + IGC_PTP_TX_TIMEOUT ))
694
+ continue ;
685
695
686
- igc_ptp_tx_timeout (adapter );
696
+ igc_ptp_tx_timeout (adapter , tstamp );
697
+ found = true;
698
+ }
699
+
700
+ if (found ) {
701
+ /* Reading the high register of the first set of timestamp registers
702
+ * clears all the equivalent bits in the TSYNCTXCTL register.
703
+ */
704
+ rd32 (IGC_TXSTMPH_0 );
705
+ }
687
706
688
- unlock :
689
707
spin_unlock_irqrestore (& adapter -> ptp_tx_lock , flags );
690
708
}
691
709
710
+ static void igc_ptp_tx_reg_to_stamp (struct igc_adapter * adapter ,
711
+ struct igc_tx_timestamp_request * tstamp , u64 regval )
712
+ {
713
+ struct skb_shared_hwtstamps shhwtstamps ;
714
+ struct sk_buff * skb ;
715
+ int adjust = 0 ;
716
+
717
+ skb = tstamp -> skb ;
718
+ if (!skb )
719
+ return ;
720
+
721
+ if (igc_ptp_systim_to_hwtstamp (adapter , & shhwtstamps , regval ))
722
+ return ;
723
+
724
+ switch (adapter -> link_speed ) {
725
+ case SPEED_10 :
726
+ adjust = IGC_I225_TX_LATENCY_10 ;
727
+ break ;
728
+ case SPEED_100 :
729
+ adjust = IGC_I225_TX_LATENCY_100 ;
730
+ break ;
731
+ case SPEED_1000 :
732
+ adjust = IGC_I225_TX_LATENCY_1000 ;
733
+ break ;
734
+ case SPEED_2500 :
735
+ adjust = IGC_I225_TX_LATENCY_2500 ;
736
+ break ;
737
+ }
738
+
739
+ shhwtstamps .hwtstamp =
740
+ ktime_add_ns (shhwtstamps .hwtstamp , adjust );
741
+
742
+ tstamp -> skb = NULL ;
743
+
744
+ skb_tstamp_tx (skb , & shhwtstamps );
745
+ dev_kfree_skb_any (skb );
746
+ }
747
+
692
748
/**
693
749
* igc_ptp_tx_hwtstamp - utility function which checks for TX time stamp
694
750
* @adapter: Board private structure
695
751
*
696
- * If we were asked to do hardware stamping and such a time stamp is
697
- * available, then it must have been for this skb here because we only
698
- * allow only one such packet into the queue .
752
+ * Check against the ready mask for which of the timestamp register
753
+ * sets are ready to be retrieved, then retrieve that and notify the
754
+ * rest of the stack .
699
755
*
700
756
* Context: Expects adapter->ptp_tx_lock to be held by caller.
701
757
*/
702
758
static void igc_ptp_tx_hwtstamp (struct igc_adapter * adapter )
703
759
{
704
- struct sk_buff * skb = adapter -> ptp_tx_skb ;
705
- struct skb_shared_hwtstamps shhwtstamps ;
706
760
struct igc_hw * hw = & adapter -> hw ;
707
- u32 tsynctxctl ;
708
- int adjust = 0 ;
709
761
u64 regval ;
762
+ u32 mask ;
763
+ int i ;
710
764
711
- if (WARN_ON_ONCE (!skb ))
712
- return ;
713
-
714
- tsynctxctl = rd32 (IGC_TSYNCTXCTL );
715
- tsynctxctl &= IGC_TSYNCTXCTL_TXTT_0 ;
716
- if (tsynctxctl ) {
765
+ mask = rd32 (IGC_TSYNCTXCTL ) & IGC_TSYNCTXCTL_TXTT_ANY ;
766
+ if (mask & IGC_TSYNCTXCTL_TXTT_0 ) {
717
767
regval = rd32 (IGC_TXSTMPL );
718
768
regval |= (u64 )rd32 (IGC_TXSTMPH ) << 32 ;
719
769
} else {
@@ -742,37 +792,30 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
742
792
txstmpl_new = rd32 (IGC_TXSTMPL );
743
793
744
794
if (txstmpl_old == txstmpl_new )
745
- return ;
795
+ goto done ;
746
796
747
797
regval = txstmpl_new ;
748
798
regval |= (u64 )rd32 (IGC_TXSTMPH ) << 32 ;
749
799
}
750
- if (igc_ptp_systim_to_hwtstamp (adapter , & shhwtstamps , regval ))
751
- return ;
752
800
753
- switch (adapter -> link_speed ) {
754
- case SPEED_10 :
755
- adjust = IGC_I225_TX_LATENCY_10 ;
756
- break ;
757
- case SPEED_100 :
758
- adjust = IGC_I225_TX_LATENCY_100 ;
759
- break ;
760
- case SPEED_1000 :
761
- adjust = IGC_I225_TX_LATENCY_1000 ;
762
- break ;
763
- case SPEED_2500 :
764
- adjust = IGC_I225_TX_LATENCY_2500 ;
765
- break ;
766
- }
801
+ igc_ptp_tx_reg_to_stamp (adapter , & adapter -> tx_tstamp [0 ], regval );
767
802
768
- shhwtstamps .hwtstamp =
769
- ktime_add_ns (shhwtstamps .hwtstamp , adjust );
803
+ done :
804
+ /* Now that the problematic first register was handled, we can
805
+ * use retrieve the timestamps from the other registers
806
+ * (starting from '1') with less complications.
807
+ */
808
+ for (i = 1 ; i < IGC_MAX_TX_TSTAMP_REGS ; i ++ ) {
809
+ struct igc_tx_timestamp_request * tstamp = & adapter -> tx_tstamp [i ];
770
810
771
- adapter -> ptp_tx_skb = NULL ;
811
+ if (!(tstamp -> mask & mask ))
812
+ continue ;
772
813
773
- /* Notify the stack and free the skb after we've unlocked */
774
- skb_tstamp_tx (skb , & shhwtstamps );
775
- dev_kfree_skb_any (skb );
814
+ regval = rd32 (tstamp -> regl );
815
+ regval |= (u64 )rd32 (tstamp -> regh ) << 32 ;
816
+
817
+ igc_ptp_tx_reg_to_stamp (adapter , tstamp , regval );
818
+ }
776
819
}
777
820
778
821
/**
@@ -788,12 +831,8 @@ void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter)
788
831
789
832
spin_lock_irqsave (& adapter -> ptp_tx_lock , flags );
790
833
791
- if (!adapter -> ptp_tx_skb )
792
- goto unlock ;
793
-
794
834
igc_ptp_tx_hwtstamp (adapter );
795
835
796
- unlock :
797
836
spin_unlock_irqrestore (& adapter -> ptp_tx_lock , flags );
798
837
}
799
838
@@ -1006,9 +1045,34 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
1006
1045
void igc_ptp_init (struct igc_adapter * adapter )
1007
1046
{
1008
1047
struct net_device * netdev = adapter -> netdev ;
1048
+ struct igc_tx_timestamp_request * tstamp ;
1009
1049
struct igc_hw * hw = & adapter -> hw ;
1010
1050
int i ;
1011
1051
1052
+ tstamp = & adapter -> tx_tstamp [0 ];
1053
+ tstamp -> mask = IGC_TSYNCTXCTL_TXTT_0 ;
1054
+ tstamp -> regl = IGC_TXSTMPL_0 ;
1055
+ tstamp -> regh = IGC_TXSTMPH_0 ;
1056
+ tstamp -> flags = 0 ;
1057
+
1058
+ tstamp = & adapter -> tx_tstamp [1 ];
1059
+ tstamp -> mask = IGC_TSYNCTXCTL_TXTT_1 ;
1060
+ tstamp -> regl = IGC_TXSTMPL_1 ;
1061
+ tstamp -> regh = IGC_TXSTMPH_1 ;
1062
+ tstamp -> flags = IGC_TX_FLAGS_TSTAMP_1 ;
1063
+
1064
+ tstamp = & adapter -> tx_tstamp [2 ];
1065
+ tstamp -> mask = IGC_TSYNCTXCTL_TXTT_2 ;
1066
+ tstamp -> regl = IGC_TXSTMPL_2 ;
1067
+ tstamp -> regh = IGC_TXSTMPH_2 ;
1068
+ tstamp -> flags = IGC_TX_FLAGS_TSTAMP_2 ;
1069
+
1070
+ tstamp = & adapter -> tx_tstamp [3 ];
1071
+ tstamp -> mask = IGC_TSYNCTXCTL_TXTT_3 ;
1072
+ tstamp -> regl = IGC_TXSTMPL_3 ;
1073
+ tstamp -> regh = IGC_TXSTMPH_3 ;
1074
+ tstamp -> flags = IGC_TX_FLAGS_TSTAMP_3 ;
1075
+
1012
1076
switch (hw -> mac .type ) {
1013
1077
case igc_i225 :
1014
1078
for (i = 0 ; i < IGC_N_SDP ; i ++ ) {
0 commit comments