@@ -558,11 +558,16 @@ static void igc_ptp_enable_rx_timestamp(struct igc_adapter *adapter)
558558static void igc_ptp_clear_tx_tstamp (struct igc_adapter * adapter )
559559{
560560 unsigned long flags ;
561+ int i ;
561562
562563 spin_lock_irqsave (& adapter -> ptp_tx_lock , flags );
563564
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+ }
566571
567572 spin_unlock_irqrestore (& adapter -> ptp_tx_lock , flags );
568573}
@@ -659,61 +664,106 @@ static int igc_ptp_set_timestamp_mode(struct igc_adapter *adapter,
659664}
660665
661666/* 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 )
663669{
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 ;
668672 adapter -> tx_hwtstamp_timeouts ++ ;
669- /* Clear the tx valid bit in TSYNCTXCTL register to enable interrupt. */
670- rd32 (IGC_TXSTMPH );
673+
671674 netdev_warn (adapter -> netdev , "Tx timestamp timeout\n" );
672675}
673676
674677void igc_ptp_tx_hang (struct igc_adapter * adapter )
675678{
679+ struct igc_tx_timestamp_request * tstamp ;
680+ struct igc_hw * hw = & adapter -> hw ;
676681 unsigned long flags ;
682+ bool found = false;
683+ int i ;
677684
678685 spin_lock_irqsave (& adapter -> ptp_tx_lock , flags );
679686
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 ;
682692
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 ;
685695
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+ }
687706
688- unlock :
689707 spin_unlock_irqrestore (& adapter -> ptp_tx_lock , flags );
690708}
691709
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+
692748/**
693749 * igc_ptp_tx_hwtstamp - utility function which checks for TX time stamp
694750 * @adapter: Board private structure
695751 *
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 .
699755 *
700756 * Context: Expects adapter->ptp_tx_lock to be held by caller.
701757 */
702758static void igc_ptp_tx_hwtstamp (struct igc_adapter * adapter )
703759{
704- struct sk_buff * skb = adapter -> ptp_tx_skb ;
705- struct skb_shared_hwtstamps shhwtstamps ;
706760 struct igc_hw * hw = & adapter -> hw ;
707- u32 tsynctxctl ;
708- int adjust = 0 ;
709761 u64 regval ;
762+ u32 mask ;
763+ int i ;
710764
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 ) {
717767 regval = rd32 (IGC_TXSTMPL );
718768 regval |= (u64 )rd32 (IGC_TXSTMPH ) << 32 ;
719769 } else {
@@ -742,37 +792,30 @@ static void igc_ptp_tx_hwtstamp(struct igc_adapter *adapter)
742792 txstmpl_new = rd32 (IGC_TXSTMPL );
743793
744794 if (txstmpl_old == txstmpl_new )
745- return ;
795+ goto done ;
746796
747797 regval = txstmpl_new ;
748798 regval |= (u64 )rd32 (IGC_TXSTMPH ) << 32 ;
749799 }
750- if (igc_ptp_systim_to_hwtstamp (adapter , & shhwtstamps , regval ))
751- return ;
752800
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 );
767802
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 ];
770810
771- adapter -> ptp_tx_skb = NULL ;
811+ if (!(tstamp -> mask & mask ))
812+ continue ;
772813
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+ }
776819}
777820
778821/**
@@ -788,12 +831,8 @@ void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter)
788831
789832 spin_lock_irqsave (& adapter -> ptp_tx_lock , flags );
790833
791- if (!adapter -> ptp_tx_skb )
792- goto unlock ;
793-
794834 igc_ptp_tx_hwtstamp (adapter );
795835
796- unlock :
797836 spin_unlock_irqrestore (& adapter -> ptp_tx_lock , flags );
798837}
799838
@@ -1006,9 +1045,34 @@ static int igc_ptp_getcrosststamp(struct ptp_clock_info *ptp,
10061045void igc_ptp_init (struct igc_adapter * adapter )
10071046{
10081047 struct net_device * netdev = adapter -> netdev ;
1048+ struct igc_tx_timestamp_request * tstamp ;
10091049 struct igc_hw * hw = & adapter -> hw ;
10101050 int i ;
10111051
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+
10121076 switch (hw -> mac .type ) {
10131077 case igc_i225 :
10141078 for (i = 0 ; i < IGC_N_SDP ; i ++ ) {
0 commit comments