prev = NULL; for (;;) {
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, m->did, prev); if (!pdev) break;
ndev++; if (m->per_socket == SKX_NUM_IMC) { for (i = 0; i < SKX_NUM_IMC; i++) if (m->devfn[i] == pdev->devfn) break; if (i == SKX_NUM_IMC) goto fail;
}
d = get_skx_dev(pdev->bus, m->busidx); if (!d) goto fail;
/* Be sure that the device is enabled */ if (unlikely(pci_enable_device(pdev) < 0)) {
skx_printk(KERN_ERR, "Couldn't enable device %04x:%04x\n",
PCI_VENDOR_ID_INTEL, m->did); goto fail;
}
switch (m->mtype) { case CHAN0: case CHAN1: case CHAN2:
pci_dev_get(pdev);
d->imc[i].chan[m->mtype].cdev = pdev; break; case ERRCHAN0: case ERRCHAN1: case ERRCHAN2:
pci_dev_get(pdev);
d->imc[i].chan[m->mtype - ERRCHAN0].edev = pdev; break; case SAD_ALL:
pci_dev_get(pdev);
d->sad_all = pdev; break; case UTIL_ALL:
pci_dev_get(pdev);
d->util_all = pdev; break; case SAD: /* * one of these devices per core, including cores * that don't exist on this SKU. Ignore any that * read a route table of zero, make sure all the * non-zero values match.
*/
pci_read_config_dword(pdev, 0xB4, ®); if (reg != 0) { if (d->mcroute == 0) {
d->mcroute = reg;
} elseif (d->mcroute != reg) {
skx_printk(KERN_ERR, "mcroute mismatch\n"); goto fail;
}
}
ndev--; break;
}
if (len - n > 0)
snprintf(msg + n, len - n, " correrrcnt[%.4x %.4x %.4x %.4x %.4x %.4x %.4x %.4x]",
corr0 & 0xffff, corr0 >> 16,
corr1 & 0xffff, corr1 >> 16,
corr2 & 0xffff, corr2 >> 16,
corr3 & 0xffff, corr3 >> 16);
}
staticbool skx_sad_decode(struct decoded_addr *res)
{ struct skx_dev *d = list_first_entry(skx_edac_list, typeof(*d), list);
u64 addr = res->addr; int i, idx, tgt, lchan, shift;
u32 sad, ilv;
u64 limit, prev_limit; int remote = 0;
/* Simple sanity check for I/O space or out of range */ if (addr >= skx_tohm || (addr >= skx_tolm && addr < BIT_ULL(32))) {
edac_dbg(0, "Address 0x%llx out of range\n", addr); returnfalse;
}
restart:
prev_limit = 0; for (i = 0; i < SKX_MAX_SAD; i++) {
SKX_GET_SAD(d, i, sad);
limit = SKX_SAD_LIMIT(sad); if (SKX_SAD_ENABLE(sad)) { if (addr >= prev_limit && addr <= limit) goto sad_found;
}
prev_limit = limit + 1;
}
edac_dbg(0, "No SAD entry for 0x%llx\n", addr); returnfalse;
sad_found:
SKX_GET_ILV(d, i, ilv);
switch (SKX_SAD_INTERLEAVE(sad)) { case 0:
idx = GET_BITFIELD(addr, 6, 8); break; case 1:
idx = GET_BITFIELD(addr, 8, 10); break; case 2:
idx = GET_BITFIELD(addr, 12, 14); break; case 3:
idx = GET_BITFIELD(addr, 30, 32); break;
}
tgt = GET_BITFIELD(ilv, 4 * idx, 4 * idx + 3);
/* If point to another node, find it and start over */ if (SKX_ILV_REMOTE(tgt)) { if (remote) {
edac_dbg(0, "Double remote!\n"); returnfalse;
}
remote = 1;
list_for_each_entry(d, skx_edac_list, list) { if (d->imc[0].src_id == SKX_ILV_TARGET(tgt)) goto restart;
}
edac_dbg(0, "Can't find node %d\n", SKX_ILV_TARGET(tgt)); returnfalse;
}
staticbool skx_tad_decode(struct decoded_addr *res)
{ int i;
u32 base, wayness, chnilvoffset; int skt_interleave_bit, chn_interleave_bit;
u64 channel_addr;
for (i = 0; i < SKX_MAX_TAD; i++) {
SKX_GET_TADBASE(res->dev, res->imc, i, base);
SKX_GET_TADWAYNESS(res->dev, res->imc, i, wayness); if (SKX_TAD_BASE(base) <= res->addr && res->addr <= SKX_TAD_LIMIT(wayness)) goto tad_found;
}
edac_dbg(0, "No TAD entry for 0x%llx\n", res->addr); returnfalse;
staticint skx_bits(u64 addr, int nbits, u8 *bits)
{ int i, res = 0;
for (i = 0; i < nbits; i++)
res |= ((addr >> bits[i]) & 1) << i; return res;
}
staticint skx_bank_bits(u64 addr, int b0, int b1, int do_xor, int x0, int x1)
{ int ret = GET_BITFIELD(addr, b0, b0) | (GET_BITFIELD(addr, b1, b1) << 1);
if (do_xor)
ret ^= GET_BITFIELD(addr, x0, x0) | (GET_BITFIELD(addr, x1, x1) << 1);
/* * skx_init: * make sure we are running on the correct cpu model * search for all the devices we need * check which DIMMs are present.
*/ staticint __init skx_init(void)
{ conststruct x86_cpu_id *id; struct res_config *cfg; conststruct munit *m; constchar *owner; int rc = 0, i, off[3] = {0xd0, 0xd4, 0xd8};
u8 mc = 0, src_id; struct skx_dev *d;
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Tony Luck");
MODULE_DESCRIPTION("MC Driver for Intel Skylake server processors");
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.13Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.