@@ -530,6 +530,284 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
530
530
}
531
531
}
532
532
533
+ struct dwxgmac3_error_desc {
534
+ bool valid ;
535
+ const char * desc ;
536
+ const char * detailed_desc ;
537
+ };
538
+
539
+ #define STAT_OFF (field ) offsetof(struct stmmac_safety_stats, field)
540
+
541
+ static void dwxgmac3_log_error (struct net_device * ndev , u32 value , bool corr ,
542
+ const char * module_name ,
543
+ const struct dwxgmac3_error_desc * desc ,
544
+ unsigned long field_offset ,
545
+ struct stmmac_safety_stats * stats )
546
+ {
547
+ unsigned long loc , mask ;
548
+ u8 * bptr = (u8 * )stats ;
549
+ unsigned long * ptr ;
550
+
551
+ ptr = (unsigned long * )(bptr + field_offset );
552
+
553
+ mask = value ;
554
+ for_each_set_bit (loc , & mask , 32 ) {
555
+ netdev_err (ndev , "Found %s error in %s: '%s: %s'\n" , corr ?
556
+ "correctable" : "uncorrectable" , module_name ,
557
+ desc [loc ].desc , desc [loc ].detailed_desc );
558
+
559
+ /* Update counters */
560
+ ptr [loc ]++ ;
561
+ }
562
+ }
563
+
564
+ static const struct dwxgmac3_error_desc dwxgmac3_mac_errors [32 ]= {
565
+ { true, "ATPES" , "Application Transmit Interface Parity Check Error" },
566
+ { true, "DPES" , "Descriptor Cache Data Path Parity Check Error" },
567
+ { true, "TPES" , "TSO Data Path Parity Check Error" },
568
+ { true, "TSOPES" , "TSO Header Data Path Parity Check Error" },
569
+ { true, "MTPES" , "MTL Data Path Parity Check Error" },
570
+ { true, "MTSPES" , "MTL TX Status Data Path Parity Check Error" },
571
+ { true, "MTBUPES" , "MAC TBU Data Path Parity Check Error" },
572
+ { true, "MTFCPES" , "MAC TFC Data Path Parity Check Error" },
573
+ { true, "ARPES" , "Application Receive Interface Data Path Parity Check Error" },
574
+ { true, "MRWCPES" , "MTL RWC Data Path Parity Check Error" },
575
+ { true, "MRRCPES" , "MTL RCC Data Path Parity Check Error" },
576
+ { true, "CWPES" , "CSR Write Data Path Parity Check Error" },
577
+ { true, "ASRPES" , "AXI Slave Read Data Path Parity Check Error" },
578
+ { true, "TTES" , "TX FSM Timeout Error" },
579
+ { true, "RTES" , "RX FSM Timeout Error" },
580
+ { true, "CTES" , "CSR FSM Timeout Error" },
581
+ { true, "ATES" , "APP FSM Timeout Error" },
582
+ { true, "PTES" , "PTP FSM Timeout Error" },
583
+ { false, "UNKNOWN" , "Unknown Error" }, /* 18 */
584
+ { false, "UNKNOWN" , "Unknown Error" }, /* 19 */
585
+ { false, "UNKNOWN" , "Unknown Error" }, /* 20 */
586
+ { true, "MSTTES" , "Master Read/Write Timeout Error" },
587
+ { true, "SLVTES" , "Slave Read/Write Timeout Error" },
588
+ { true, "ATITES" , "Application Timeout on ATI Interface Error" },
589
+ { true, "ARITES" , "Application Timeout on ARI Interface Error" },
590
+ { true, "FSMPES" , "FSM State Parity Error" },
591
+ { false, "UNKNOWN" , "Unknown Error" }, /* 26 */
592
+ { false, "UNKNOWN" , "Unknown Error" }, /* 27 */
593
+ { false, "UNKNOWN" , "Unknown Error" }, /* 28 */
594
+ { false, "UNKNOWN" , "Unknown Error" }, /* 29 */
595
+ { false, "UNKNOWN" , "Unknown Error" }, /* 30 */
596
+ { true, "CPI" , "Control Register Parity Check Error" },
597
+ };
598
+
599
+ static void dwxgmac3_handle_mac_err (struct net_device * ndev ,
600
+ void __iomem * ioaddr , bool correctable ,
601
+ struct stmmac_safety_stats * stats )
602
+ {
603
+ u32 value ;
604
+
605
+ value = readl (ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS );
606
+ writel (value , ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS );
607
+
608
+ dwxgmac3_log_error (ndev , value , correctable , "MAC" ,
609
+ dwxgmac3_mac_errors , STAT_OFF (mac_errors ), stats );
610
+ }
611
+
612
+ static const struct dwxgmac3_error_desc dwxgmac3_mtl_errors [32 ]= {
613
+ { true, "TXCES" , "MTL TX Memory Error" },
614
+ { true, "TXAMS" , "MTL TX Memory Address Mismatch Error" },
615
+ { true, "TXUES" , "MTL TX Memory Error" },
616
+ { false, "UNKNOWN" , "Unknown Error" }, /* 3 */
617
+ { true, "RXCES" , "MTL RX Memory Error" },
618
+ { true, "RXAMS" , "MTL RX Memory Address Mismatch Error" },
619
+ { true, "RXUES" , "MTL RX Memory Error" },
620
+ { false, "UNKNOWN" , "Unknown Error" }, /* 7 */
621
+ { true, "ECES" , "MTL EST Memory Error" },
622
+ { true, "EAMS" , "MTL EST Memory Address Mismatch Error" },
623
+ { true, "EUES" , "MTL EST Memory Error" },
624
+ { false, "UNKNOWN" , "Unknown Error" }, /* 11 */
625
+ { true, "RPCES" , "MTL RX Parser Memory Error" },
626
+ { true, "RPAMS" , "MTL RX Parser Memory Address Mismatch Error" },
627
+ { true, "RPUES" , "MTL RX Parser Memory Error" },
628
+ { false, "UNKNOWN" , "Unknown Error" }, /* 15 */
629
+ { false, "UNKNOWN" , "Unknown Error" }, /* 16 */
630
+ { false, "UNKNOWN" , "Unknown Error" }, /* 17 */
631
+ { false, "UNKNOWN" , "Unknown Error" }, /* 18 */
632
+ { false, "UNKNOWN" , "Unknown Error" }, /* 19 */
633
+ { false, "UNKNOWN" , "Unknown Error" }, /* 20 */
634
+ { false, "UNKNOWN" , "Unknown Error" }, /* 21 */
635
+ { false, "UNKNOWN" , "Unknown Error" }, /* 22 */
636
+ { false, "UNKNOWN" , "Unknown Error" }, /* 23 */
637
+ { false, "UNKNOWN" , "Unknown Error" }, /* 24 */
638
+ { false, "UNKNOWN" , "Unknown Error" }, /* 25 */
639
+ { false, "UNKNOWN" , "Unknown Error" }, /* 26 */
640
+ { false, "UNKNOWN" , "Unknown Error" }, /* 27 */
641
+ { false, "UNKNOWN" , "Unknown Error" }, /* 28 */
642
+ { false, "UNKNOWN" , "Unknown Error" }, /* 29 */
643
+ { false, "UNKNOWN" , "Unknown Error" }, /* 30 */
644
+ { false, "UNKNOWN" , "Unknown Error" }, /* 31 */
645
+ };
646
+
647
+ static void dwxgmac3_handle_mtl_err (struct net_device * ndev ,
648
+ void __iomem * ioaddr , bool correctable ,
649
+ struct stmmac_safety_stats * stats )
650
+ {
651
+ u32 value ;
652
+
653
+ value = readl (ioaddr + XGMAC_MTL_ECC_INT_STATUS );
654
+ writel (value , ioaddr + XGMAC_MTL_ECC_INT_STATUS );
655
+
656
+ dwxgmac3_log_error (ndev , value , correctable , "MTL" ,
657
+ dwxgmac3_mtl_errors , STAT_OFF (mtl_errors ), stats );
658
+ }
659
+
660
+ static const struct dwxgmac3_error_desc dwxgmac3_dma_errors [32 ]= {
661
+ { true, "TCES" , "DMA TSO Memory Error" },
662
+ { true, "TAMS" , "DMA TSO Memory Address Mismatch Error" },
663
+ { true, "TUES" , "DMA TSO Memory Error" },
664
+ { false, "UNKNOWN" , "Unknown Error" }, /* 3 */
665
+ { true, "DCES" , "DMA DCACHE Memory Error" },
666
+ { true, "DAMS" , "DMA DCACHE Address Mismatch Error" },
667
+ { true, "DUES" , "DMA DCACHE Memory Error" },
668
+ { false, "UNKNOWN" , "Unknown Error" }, /* 7 */
669
+ { false, "UNKNOWN" , "Unknown Error" }, /* 8 */
670
+ { false, "UNKNOWN" , "Unknown Error" }, /* 9 */
671
+ { false, "UNKNOWN" , "Unknown Error" }, /* 10 */
672
+ { false, "UNKNOWN" , "Unknown Error" }, /* 11 */
673
+ { false, "UNKNOWN" , "Unknown Error" }, /* 12 */
674
+ { false, "UNKNOWN" , "Unknown Error" }, /* 13 */
675
+ { false, "UNKNOWN" , "Unknown Error" }, /* 14 */
676
+ { false, "UNKNOWN" , "Unknown Error" }, /* 15 */
677
+ { false, "UNKNOWN" , "Unknown Error" }, /* 16 */
678
+ { false, "UNKNOWN" , "Unknown Error" }, /* 17 */
679
+ { false, "UNKNOWN" , "Unknown Error" }, /* 18 */
680
+ { false, "UNKNOWN" , "Unknown Error" }, /* 19 */
681
+ { false, "UNKNOWN" , "Unknown Error" }, /* 20 */
682
+ { false, "UNKNOWN" , "Unknown Error" }, /* 21 */
683
+ { false, "UNKNOWN" , "Unknown Error" }, /* 22 */
684
+ { false, "UNKNOWN" , "Unknown Error" }, /* 23 */
685
+ { false, "UNKNOWN" , "Unknown Error" }, /* 24 */
686
+ { false, "UNKNOWN" , "Unknown Error" }, /* 25 */
687
+ { false, "UNKNOWN" , "Unknown Error" }, /* 26 */
688
+ { false, "UNKNOWN" , "Unknown Error" }, /* 27 */
689
+ { false, "UNKNOWN" , "Unknown Error" }, /* 28 */
690
+ { false, "UNKNOWN" , "Unknown Error" }, /* 29 */
691
+ { false, "UNKNOWN" , "Unknown Error" }, /* 30 */
692
+ { false, "UNKNOWN" , "Unknown Error" }, /* 31 */
693
+ };
694
+
695
+ static void dwxgmac3_handle_dma_err (struct net_device * ndev ,
696
+ void __iomem * ioaddr , bool correctable ,
697
+ struct stmmac_safety_stats * stats )
698
+ {
699
+ u32 value ;
700
+
701
+ value = readl (ioaddr + XGMAC_DMA_ECC_INT_STATUS );
702
+ writel (value , ioaddr + XGMAC_DMA_ECC_INT_STATUS );
703
+
704
+ dwxgmac3_log_error (ndev , value , correctable , "DMA" ,
705
+ dwxgmac3_dma_errors , STAT_OFF (dma_errors ), stats );
706
+ }
707
+
708
+ static int dwxgmac3_safety_feat_config (void __iomem * ioaddr , unsigned int asp )
709
+ {
710
+ u32 value ;
711
+
712
+ if (!asp )
713
+ return - EINVAL ;
714
+
715
+ /* 1. Enable Safety Features */
716
+ writel (0x0 , ioaddr + XGMAC_MTL_ECC_CONTROL );
717
+
718
+ /* 2. Enable MTL Safety Interrupts */
719
+ value = readl (ioaddr + XGMAC_MTL_ECC_INT_ENABLE );
720
+ value |= XGMAC_RPCEIE ; /* RX Parser Memory Correctable Error */
721
+ value |= XGMAC_ECEIE ; /* EST Memory Correctable Error */
722
+ value |= XGMAC_RXCEIE ; /* RX Memory Correctable Error */
723
+ value |= XGMAC_TXCEIE ; /* TX Memory Correctable Error */
724
+ writel (value , ioaddr + XGMAC_MTL_ECC_INT_ENABLE );
725
+
726
+ /* 3. Enable DMA Safety Interrupts */
727
+ value = readl (ioaddr + XGMAC_DMA_ECC_INT_ENABLE );
728
+ value |= XGMAC_DCEIE ; /* Descriptor Cache Memory Correctable Error */
729
+ value |= XGMAC_TCEIE ; /* TSO Memory Correctable Error */
730
+ writel (value , ioaddr + XGMAC_DMA_ECC_INT_ENABLE );
731
+
732
+ /* Only ECC Protection for External Memory feature is selected */
733
+ if (asp <= 0x1 )
734
+ return 0 ;
735
+
736
+ /* 4. Enable Parity and Timeout for FSM */
737
+ value = readl (ioaddr + XGMAC_MAC_FSM_CONTROL );
738
+ value |= XGMAC_PRTYEN ; /* FSM Parity Feature */
739
+ value |= XGMAC_TMOUTEN ; /* FSM Timeout Feature */
740
+ writel (value , ioaddr + XGMAC_MAC_FSM_CONTROL );
741
+
742
+ return 0 ;
743
+ }
744
+
745
+ static int dwxgmac3_safety_feat_irq_status (struct net_device * ndev ,
746
+ void __iomem * ioaddr ,
747
+ unsigned int asp ,
748
+ struct stmmac_safety_stats * stats )
749
+ {
750
+ bool err , corr ;
751
+ u32 mtl , dma ;
752
+ int ret = 0 ;
753
+
754
+ if (!asp )
755
+ return - EINVAL ;
756
+
757
+ mtl = readl (ioaddr + XGMAC_MTL_SAFETY_INT_STATUS );
758
+ dma = readl (ioaddr + XGMAC_DMA_SAFETY_INT_STATUS );
759
+
760
+ err = (mtl & XGMAC_MCSIS ) || (dma & XGMAC_MCSIS );
761
+ corr = false;
762
+ if (err ) {
763
+ dwxgmac3_handle_mac_err (ndev , ioaddr , corr , stats );
764
+ ret |= !corr ;
765
+ }
766
+
767
+ err = (mtl & (XGMAC_MEUIS | XGMAC_MECIS )) ||
768
+ (dma & (XGMAC_MSUIS | XGMAC_MSCIS ));
769
+ corr = (mtl & XGMAC_MECIS ) || (dma & XGMAC_MSCIS );
770
+ if (err ) {
771
+ dwxgmac3_handle_mtl_err (ndev , ioaddr , corr , stats );
772
+ ret |= !corr ;
773
+ }
774
+
775
+ err = dma & (XGMAC_DEUIS | XGMAC_DECIS );
776
+ corr = dma & XGMAC_DECIS ;
777
+ if (err ) {
778
+ dwxgmac3_handle_dma_err (ndev , ioaddr , corr , stats );
779
+ ret |= !corr ;
780
+ }
781
+
782
+ return ret ;
783
+ }
784
+
785
+ static const struct dwxgmac3_error {
786
+ const struct dwxgmac3_error_desc * desc ;
787
+ } dwxgmac3_all_errors [] = {
788
+ { dwxgmac3_mac_errors },
789
+ { dwxgmac3_mtl_errors },
790
+ { dwxgmac3_dma_errors },
791
+ };
792
+
793
+ static int dwxgmac3_safety_feat_dump (struct stmmac_safety_stats * stats ,
794
+ int index , unsigned long * count ,
795
+ const char * * desc )
796
+ {
797
+ int module = index / 32 , offset = index % 32 ;
798
+ unsigned long * ptr = (unsigned long * )stats ;
799
+
800
+ if (module >= ARRAY_SIZE (dwxgmac3_all_errors ))
801
+ return - EINVAL ;
802
+ if (!dwxgmac3_all_errors [module ].desc [offset ].valid )
803
+ return - EINVAL ;
804
+ if (count )
805
+ * count = * (ptr + index );
806
+ if (desc )
807
+ * desc = dwxgmac3_all_errors [module ].desc [offset ].desc ;
808
+ return 0 ;
809
+ }
810
+
533
811
const struct stmmac_ops dwxgmac210_ops = {
534
812
.core_init = dwxgmac2_core_init ,
535
813
.set_mac = dwxgmac2_set_mac ,
@@ -559,6 +837,9 @@ const struct stmmac_ops dwxgmac210_ops = {
559
837
.pcs_get_adv_lp = NULL ,
560
838
.debug = NULL ,
561
839
.set_filter = dwxgmac2_set_filter ,
840
+ .safety_feat_config = dwxgmac3_safety_feat_config ,
841
+ .safety_feat_irq_status = dwxgmac3_safety_feat_irq_status ,
842
+ .safety_feat_dump = dwxgmac3_safety_feat_dump ,
562
843
.set_mac_loopback = dwxgmac2_set_mac_loopback ,
563
844
.rss_configure = dwxgmac2_rss_configure ,
564
845
.update_vlan_hash = dwxgmac2_update_vlan_hash ,
0 commit comments