@@ -658,13 +658,49 @@ static struct pci_dev *get_ddr_munit(struct skx_dev *d, int i, u32 *offset, unsi
658
658
return mdev ;
659
659
}
660
660
661
+ /**
662
+ * i10nm_imc_absent() - Check whether the memory controller @imc is absent
663
+ *
664
+ * @imc : The pointer to the structure of memory controller EDAC device.
665
+ *
666
+ * RETURNS : true if the memory controller EDAC device is absent, false otherwise.
667
+ */
668
+ static bool i10nm_imc_absent (struct skx_imc * imc )
669
+ {
670
+ u32 mcmtr ;
671
+ int i ;
672
+
673
+ switch (res_cfg -> type ) {
674
+ case SPR :
675
+ for (i = 0 ; i < res_cfg -> ddr_chan_num ; i ++ ) {
676
+ mcmtr = I10NM_GET_MCMTR (imc , i );
677
+ edac_dbg (1 , "ch%d mcmtr reg %x\n" , i , mcmtr );
678
+ if (mcmtr != ~0 )
679
+ return false;
680
+ }
681
+
682
+ /*
683
+ * Some workstations' absent memory controllers still
684
+ * appear as PCIe devices, misleading the EDAC driver.
685
+ * By observing that the MMIO registers of these absent
686
+ * memory controllers consistently hold the value of ~0.
687
+ *
688
+ * We identify a memory controller as absent by checking
689
+ * if its MMIO register "mcmtr" == ~0 in all its channels.
690
+ */
691
+ return true;
692
+ default :
693
+ return false;
694
+ }
695
+ }
696
+
661
697
static int i10nm_get_ddr_munits (void )
662
698
{
663
699
struct pci_dev * mdev ;
664
700
void __iomem * mbase ;
665
701
unsigned long size ;
666
702
struct skx_dev * d ;
667
- int i , j = 0 ;
703
+ int i , lmc , j = 0 ;
668
704
u32 reg , off ;
669
705
u64 base ;
670
706
@@ -690,7 +726,7 @@ static int i10nm_get_ddr_munits(void)
690
726
edac_dbg (2 , "socket%d mmio base 0x%llx (reg 0x%x)\n" ,
691
727
j ++ , base , reg );
692
728
693
- for (i = 0 ; i < res_cfg -> ddr_imc_num ; i ++ ) {
729
+ for (lmc = 0 , i = 0 ; i < res_cfg -> ddr_imc_num ; i ++ ) {
694
730
mdev = get_ddr_munit (d , i , & off , & size );
695
731
696
732
if (i == 0 && !mdev ) {
@@ -700,8 +736,6 @@ static int i10nm_get_ddr_munits(void)
700
736
if (!mdev )
701
737
continue ;
702
738
703
- d -> imc [i ].mdev = mdev ;
704
-
705
739
edac_dbg (2 , "mc%d mmio base 0x%llx size 0x%lx (reg 0x%x)\n" ,
706
740
i , base + off , size , reg );
707
741
@@ -712,7 +746,17 @@ static int i10nm_get_ddr_munits(void)
712
746
return - ENODEV ;
713
747
}
714
748
715
- d -> imc [i ].mbase = mbase ;
749
+ d -> imc [lmc ].mbase = mbase ;
750
+ if (i10nm_imc_absent (& d -> imc [lmc ])) {
751
+ pci_dev_put (mdev );
752
+ iounmap (mbase );
753
+ d -> imc [lmc ].mbase = NULL ;
754
+ edac_dbg (2 , "Skip absent mc%d\n" , i );
755
+ continue ;
756
+ } else {
757
+ d -> imc [lmc ].mdev = mdev ;
758
+ lmc ++ ;
759
+ }
716
760
}
717
761
}
718
762
0 commit comments