sb_edac: search devices using product id
[cascardo/linux.git] / drivers / edac / sb_edac.c
index deea0dc..3411f50 100644 (file)
@@ -176,8 +176,6 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
 
 #define SAD_CONTROL    0xf4
 
-#define NODE_ID(reg)           GET_BITFIELD(reg, 0, 2)
-
 /* Device 14 function 0 */
 
 static const u32 tad_dram_rule[] = {
@@ -235,7 +233,6 @@ static const u32 rir_way_limit[] = {
 
 #define IS_RIR_VALID(reg)      GET_BITFIELD(reg, 31, 31)
 #define RIR_WAY(reg)           GET_BITFIELD(reg, 28, 29)
-#define RIR_LIMIT(reg)         ((GET_BITFIELD(reg,  1, 10) << 29)| 0x1fffffff)
 
 #define MAX_RIR_WAY    8
 
@@ -279,8 +276,6 @@ static const u32 correrrthrsld[] = {
 
 #define IB_RANK_CFG_A          0x0320
 
-#define IS_RDIMM_ENABLED(reg)          GET_BITFIELD(reg, 11, 11)
-
 /*
  * sbridge structs
  */
@@ -300,11 +295,14 @@ struct sbridge_info {
        u32             rankcfgr;
        u64             (*get_tolm)(struct sbridge_pvt *pvt);
        u64             (*get_tohm)(struct sbridge_pvt *pvt);
+       u64             (*rir_limit)(u32 reg);
        const u32       *dram_rule;
        const u32       *interleave_list;
        const struct interleave_pkg *interleave_pkg;
        u8              max_sad;
        u8              max_interleave;
+       u8              (*get_node_id)(struct sbridge_pvt *pvt);
+       enum mem_type   (*get_memory_type)(struct sbridge_pvt *pvt);
 };
 
 struct sbridge_channel {
@@ -313,8 +311,6 @@ struct sbridge_channel {
 };
 
 struct pci_id_descr {
-       int                     dev;
-       int                     func;
        int                     dev_id;
        int                     optional;
 };
@@ -362,31 +358,29 @@ struct sbridge_pvt {
        u64                     tolm, tohm;
 };
 
-#define PCI_DESCR(device, function, device_id, opt)    \
-       .dev = (device),                                \
-       .func = (function),                             \
-       .dev_id = (device_id),                          \
+#define PCI_DESCR(device_id, opt)      \
+       .dev_id = (device_id),          \
        .optional = opt
 
 static const struct pci_id_descr pci_dev_descr_sbridge[] = {
                /* Processor Home Agent */
-       { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)      },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)     },
 
                /* Memory controller */
-       { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)       },
-       { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)      },
-       { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)     },
-       { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)     },
-       { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)     },
-       { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)     },
-       { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)    },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)      },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)     },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)    },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)    },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)    },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)    },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)   },
 
                /* System Address Decoder */
-       { PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)         },
-       { PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)         },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)        },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)        },
 
                /* Broadcast Registers */
-       { PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)           },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)          },
 };
 
 #define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -423,34 +417,34 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = {
 
 static const struct pci_id_descr pci_dev_descr_ibridge[] = {
                /* Processor Home Agent */
-       { PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)      },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)             },
 
                /* Memory controller */
-       { PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)   },
-       { PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)  },
-       { PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0) },
-       { PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0) },
-       { PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0) },
-       { PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0) },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)          },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)         },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0)        },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0)        },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0)        },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0)        },
 
                /* System Address Decoder */
-       { PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)          },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)                 },
 
                /* Broadcast Registers */
-       { PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)          },
-       { PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)          },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)                 },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)                 },
 
                /* Optional, mode 2HA */
-       { PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)      },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)             },
 #if 0
-       { PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)   },
-       { PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1)  },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)  },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1) },
 #endif
-       { PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1) },
-       { PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1) },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1)        },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1)        },
 
-       { PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
-       { PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1)      },
+       { PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1)      },
 };
 
 static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
@@ -588,6 +582,37 @@ static u64 ibridge_get_tohm(struct sbridge_pvt *pvt)
        return GET_TOHM(reg);
 }
 
+static u64 rir_limit(u32 reg)
+{
+       return ((u64)GET_BITFIELD(reg,  1, 10) << 29) | 0x1fffffff;
+}
+
+static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
+{
+       u32 reg;
+       enum mem_type mtype;
+
+       if (pvt->pci_ddrio) {
+               pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
+                                     &reg);
+               if (GET_BITFIELD(reg, 11, 11))
+                       /* FIXME: Can also be LRDIMM */
+                       mtype = MEM_RDDR3;
+               else
+                       mtype = MEM_DDR3;
+       } else
+               mtype = MEM_UNKNOWN;
+
+       return mtype;
+}
+
+static u8 get_node_id(struct sbridge_pvt *pvt)
+{
+       u32 reg;
+       pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
+       return GET_BITFIELD(reg, 0, 2);
+}
+
 static inline u8 sad_pkg_socket(u8 pkg)
 {
        /* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
@@ -602,44 +627,38 @@ static inline u8 sad_pkg_ha(u8 pkg)
 /****************************************************************************
                        Memory check routines
  ****************************************************************************/
-static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
-                                         unsigned func)
+static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
 {
-       struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
-       int i;
-
-       if (!sbridge_dev)
-               return NULL;
-
-       for (i = 0; i < sbridge_dev->n_devs; i++) {
-               if (!sbridge_dev->pdev[i])
-                       continue;
+       struct pci_dev *pdev = NULL;
 
-               if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
-                   PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
-                       edac_dbg(1, "Associated %02x.%02x.%d with %p\n",
-                                bus, slot, func, sbridge_dev->pdev[i]);
-                       return sbridge_dev->pdev[i];
-               }
-       }
+       do {
+               pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
+               if (pdev && pdev->bus->number == bus)
+                       break;
+       } while (pdev);
 
-       return NULL;
+       return pdev;
 }
 
 /**
  * check_if_ecc_is_active() - Checks if ECC is active
  * bus:                Device bus
  */
-static int check_if_ecc_is_active(const u8 bus)
+static int check_if_ecc_is_active(const u8 bus, enum type type)
 {
        struct pci_dev *pdev = NULL;
-       u32 mcmtr;
+       u32 mcmtr, id;
 
-       pdev = get_pdev_slot_func(bus, 15, 0);
+       if (type == IVY_BRIDGE)
+               id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
+       else
+               id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
+
+       pdev = get_pdev_same_bus(bus, id);
        if (!pdev) {
                sbridge_printk(KERN_ERR, "Couldn't find PCI device "
-                                       "%2x.%02d.%d!!!\n",
-                                       bus, 15, 0);
+                                       "%04x:%04x! on bus %02d\n",
+                                       PCI_VENDOR_ID_INTEL, id, bus);
                return -ENODEV;
        }
 
@@ -664,8 +683,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
        pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
        pvt->sbridge_dev->source_id = SOURCE_ID(reg);
 
-       pci_read_config_dword(pvt->pci_br0, SAD_CONTROL, &reg);
-       pvt->sbridge_dev->node_id = NODE_ID(reg);
+       pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
        edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
                 pvt->sbridge_dev->mc,
                 pvt->sbridge_dev->node_id,
@@ -698,21 +716,13 @@ static int get_dimm_config(struct mem_ctl_info *mci)
                pvt->is_close_pg = false;
        }
 
-       if (pvt->pci_ddrio) {
-               pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
-                                     &reg);
-               if (IS_RDIMM_ENABLED(reg)) {
-                       /* FIXME: Can also be LRDIMM */
-                       edac_dbg(0, "Memory is registered\n");
-                       mtype = MEM_RDDR3;
-               } else {
-                       edac_dbg(0, "Memory is unregistered\n");
-                       mtype = MEM_DDR3;
-               }
-       } else {
+       mtype = pvt->info.get_memory_type(pvt);
+       if (mtype == MEM_RDDR3)
+               edac_dbg(0, "Memory is registered\n");
+       else if (mtype == MEM_UNKNOWN)
                edac_dbg(0, "Cannot determine memory type\n");
-               mtype = MEM_UNKNOWN;
-       }
+       else
+               edac_dbg(0, "Memory is unregistered\n");
 
        /* On all supported DDR3 DIMM types, there are 8 banks available */
        banks = 8;
@@ -887,7 +897,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
                        if (!IS_RIR_VALID(reg))
                                continue;
 
-                       tmp_mb = RIR_LIMIT(reg) >> 20;
+                       tmp_mb = pvt->info.rir_limit(reg) >> 20;
                        rir_way = 1 << RIR_WAY(reg);
                        mb = div_u64_rem(tmp_mb, 1000, &kb);
                        edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n",
@@ -1181,7 +1191,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
                if (!IS_RIR_VALID(reg))
                        continue;
 
-               limit = RIR_LIMIT(reg);
+               limit = pvt->info.rir_limit(reg);
                mb = div_u64_rem(limit >> 20, 1000, &kb);
                edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n",
                         n_rir,
@@ -1259,13 +1269,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
 {
        struct sbridge_dev *sbridge_dev;
        const struct pci_id_descr *dev_descr = &table->descr[devno];
-
        struct pci_dev *pdev = NULL;
        u8 bus = 0;
 
        sbridge_printk(KERN_DEBUG,
-               "Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
-               dev_descr->dev, dev_descr->func,
+               "Seeking for: PCI ID %04x:%04x\n",
                PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
        pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1280,12 +1288,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
                if (dev_descr->optional)
                        return 0;
 
+               /* if the HA wasn't found */
                if (devno == 0)
                        return -ENODEV;
 
                sbridge_printk(KERN_INFO,
-                       "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
-                       dev_descr->dev, dev_descr->func,
+                       "Device not found: %04x:%04x\n",
                        PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
                /* End of list, leave */
@@ -1305,9 +1313,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
 
        if (sbridge_dev->pdev[devno]) {
                sbridge_printk(KERN_ERR,
-                       "Duplicated device for "
-                       "dev %02x:%d.%d PCI ID %04x:%04x\n",
-                       bus, dev_descr->dev, dev_descr->func,
+                       "Duplicated device for %04x:%04x\n",
                        PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
                pci_dev_put(pdev);
                return -ENODEV;
@@ -1315,30 +1321,15 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
 
        sbridge_dev->pdev[devno] = pdev;
 
-       /* Sanity check */
-       if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
-                       PCI_FUNC(pdev->devfn) != dev_descr->func)) {
-               sbridge_printk(KERN_ERR,
-                       "Device PCI ID %04x:%04x "
-                       "has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
-                       PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
-                       bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
-                       bus, dev_descr->dev, dev_descr->func);
-               return -ENODEV;
-       }
-
        /* Be sure that the device is enabled */
        if (unlikely(pci_enable_device(pdev) < 0)) {
                sbridge_printk(KERN_ERR,
-                       "Couldn't enable "
-                       "dev %02x:%d.%d PCI ID %04x:%04x\n",
-                       bus, dev_descr->dev, dev_descr->func,
+                       "Couldn't enable %04x:%04x\n",
                        PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
                return -ENODEV;
        }
 
-       edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
-                bus, dev_descr->dev, dev_descr->func,
+       edac_dbg(0, "Detected %04x:%04x\n",
                 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
        /*
@@ -1355,8 +1346,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
 
 /*
  * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
- *                          device/functions we want to reference for this driver.
- *                          Need to 'get' device 16 func 1 and func 2.
+ *                          devices we want to reference for this driver.
  * @num_mc: pointer to the memory controllers count, to be incremented in case
  *         of success.
  * @table: model specific table
@@ -1396,79 +1386,51 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
 {
        struct sbridge_pvt *pvt = mci->pvt_info;
        struct pci_dev *pdev;
-       int i, func, slot;
+       int i;
 
        for (i = 0; i < sbridge_dev->n_devs; i++) {
                pdev = sbridge_dev->pdev[i];
                if (!pdev)
                        continue;
-               slot = PCI_SLOT(pdev->devfn);
-               func = PCI_FUNC(pdev->devfn);
-               switch (slot) {
-               case 12:
-                       switch (func) {
-                       case 6:
-                               pvt->pci_sad0 = pdev;
-                               break;
-                       case 7:
-                               pvt->pci_sad1 = pdev;
-                               break;
-                       default:
-                               goto error;
-                       }
+
+               switch (pdev->device) {
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0:
+                       pvt->pci_sad0 = pdev;
                        break;
-               case 13:
-                       switch (func) {
-                       case 6:
-                               pvt->pci_br0 = pdev;
-                               break;
-                       default:
-                               goto error;
-                       }
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1:
+                       pvt->pci_sad1 = pdev;
                        break;
-               case 14:
-                       switch (func) {
-                       case 0:
-                               pvt->pci_ha0 = pdev;
-                               break;
-                       default:
-                               goto error;
-                       }
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_BR:
+                       pvt->pci_br0 = pdev;
                        break;
-               case 15:
-                       switch (func) {
-                       case 0:
-                               pvt->pci_ta = pdev;
-                               break;
-                       case 1:
-                               pvt->pci_ras = pdev;
-                               break;
-                       case 2:
-                       case 3:
-                       case 4:
-                       case 5:
-                               pvt->pci_tad[func - 2] = pdev;
-                               break;
-                       default:
-                               goto error;
-                       }
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
+                       pvt->pci_ha0 = pdev;
                        break;
-               case 17:
-                       switch (func) {
-                       case 0:
-                               pvt->pci_ddrio = pdev;
-                               break;
-                       default:
-                               goto error;
-                       }
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
+                       pvt->pci_ta = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS:
+                       pvt->pci_ras = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0:
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1:
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
+               {
+                       int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
+                       pvt->pci_tad[id] = pdev;
+               }
+                       break;
+               case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
+                       pvt->pci_ddrio = pdev;
                        break;
                default:
                        goto error;
                }
 
-               edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
+               edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n",
+                        pdev->vendor, pdev->device,
                         sbridge_dev->bus,
-                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
                         pdev);
        }
 
@@ -1488,9 +1450,8 @@ enodev:
        return -ENODEV;
 
 error:
-       sbridge_printk(KERN_ERR, "Device %d, function %d "
-                     "is out of the expected range\n",
-                     slot, func);
+       sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n",
+                      PCI_VENDOR_ID_INTEL, pdev->device);
        return -EINVAL;
 }
 
@@ -1499,7 +1460,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
 {
        struct sbridge_pvt *pvt = mci->pvt_info;
        struct pci_dev *pdev, *tmp;
-       int i, func, slot;
+       int i;
        bool mode_2ha = false;
 
        tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1513,79 +1474,60 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
                pdev = sbridge_dev->pdev[i];
                if (!pdev)
                        continue;
-               slot = PCI_SLOT(pdev->devfn);
-               func = PCI_FUNC(pdev->devfn);
 
-               switch (slot) {
-               case 14:
-                       if (func == 0) {
-                               pvt->pci_ha0 = pdev;
-                               break;
-                       }
-                       goto error;
-               case 15:
-                       switch (func) {
-                       case 0:
-                               pvt->pci_ta = pdev;
-                               break;
-                       case 1:
-                               pvt->pci_ras = pdev;
-                               break;
-                       case 4:
-                       case 5:
-                               /* if we have 2 HAs active, channels 2 and 3
-                                * are in other device */
-                               if (mode_2ha)
-                                       break;
-                               /* fall through */
-                       case 2:
-                       case 3:
-                               pvt->pci_tad[func - 2] = pdev;
+               switch (pdev->device) {
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
+                       pvt->pci_ha0 = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
+                       pvt->pci_ta = pdev;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
+                       pvt->pci_ras = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
+                       /* if we have 2 HAs active, channels 2 and 3
+                        * are in other device */
+                       if (mode_2ha)
                                break;
-                       default:
-                               goto error;
-                       }
+                       /* fall through */
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
+               {
+                       int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0;
+                       pvt->pci_tad[id] = pdev;
+               }
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0:
+                       pvt->pci_ddrio = pdev;
                        break;
-               case 17:
-                       if (func == 4) {
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0:
+                       if (!mode_2ha)
                                pvt->pci_ddrio = pdev;
-                               break;
-                       } else if (func == 0) {
-                               if (!mode_2ha)
-                                       pvt->pci_ddrio = pdev;
-                               break;
-                       }
-                       goto error;
-               case 22:
-                       switch (func) {
-                       case 0:
-                               pvt->pci_sad0 = pdev;
-                               break;
-                       case 1:
-                               pvt->pci_br0 = pdev;
-                               break;
-                       case 2:
-                               pvt->pci_br1 = pdev;
-                               break;
-                       default:
-                               goto error;
-                       }
                        break;
-               case 28:
-                       if (func == 0) {
-                               pvt->pci_ha1 = pdev;
-                               break;
-                       }
-                       goto error;
-               case 29:
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD:
+                       pvt->pci_sad0 = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0:
+                       pvt->pci_br0 = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
+                       pvt->pci_br1 = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
+                       pvt->pci_ha1 = pdev;
+                       break;
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
+               case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
+               {
+                       int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2;
+
                        /* we shouldn't have this device if we have just one
                         * HA present */
                        WARN_ON(!mode_2ha);
-                       if (func == 2 || func == 3) {
-                               pvt->pci_tad[func] = pdev;
-                               break;
-                       }
-                       goto error;
+                       pvt->pci_tad[id] = pdev;
+               }
+                       break;
                default:
                        goto error;
                }
@@ -1614,8 +1556,8 @@ enodev:
 
 error:
        sbridge_printk(KERN_ERR,
-                      "Device %d, function %d is out of the expected range\n",
-                      slot, func);
+                      "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL,
+                       pdev->device);
        return -EINVAL;
 }
 
@@ -1932,7 +1874,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
        int rc;
 
        /* Check the number of active and not disabled channels */
-       rc = check_if_ecc_is_active(sbridge_dev->bus);
+       rc = check_if_ecc_is_active(sbridge_dev->bus, type);
        if (unlikely(rc < 0))
                return rc;
 
@@ -1976,6 +1918,9 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
                pvt->info.get_tolm = ibridge_get_tolm;
                pvt->info.get_tohm = ibridge_get_tohm;
                pvt->info.dram_rule = ibridge_dram_rule;
+               pvt->info.get_memory_type = get_memory_type;
+               pvt->info.get_node_id = get_node_id;
+               pvt->info.rir_limit = rir_limit;
                pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
                pvt->info.interleave_list = ibridge_interleave_list;
                pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -1991,6 +1936,9 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
                pvt->info.get_tolm = sbridge_get_tolm;
                pvt->info.get_tohm = sbridge_get_tohm;
                pvt->info.dram_rule = sbridge_dram_rule;
+               pvt->info.get_memory_type = get_memory_type;
+               pvt->info.get_node_id = get_node_id;
+               pvt->info.rir_limit = rir_limit;
                pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
                pvt->info.interleave_list = sbridge_interleave_list;
                pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);