EDAC changes for v5.3
-----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJdI2fNAAoJEKurIx+X31iBJVoP/jSJbSY49IcJ7st8uolxJ9d9 84ol7TNBnKeKeUXxrQom2hJsqUnQzaUgw3FKfxX0hmYG5Q9xGS8c+BlW4Giei+Ur baGLO7/UEudWcaez3yOQF+R+yVfsLEATN7gSHcrG81aDyR0F6sMPVCOJOj3hqqnY pZpfxR2+52Xx+Bt8KUUQziCK8qghQYKqHUQUz7R83L0gbbx5+hTAT08h4FCxE8Vx fhntQuteJ2PfYgXlmfv+ZLE4HSHaAlokOnVXJhK+7tMdwDD2we+pL0zr5XdbkZYc If6p9LgJinMe5P5gJSvxT1idWmomKIQqazaC17ff/anLRySrzi9F2oPAGtVI2tvK NekoO3oo4s+xONXfe7Q922rIGt/4vZj6tcqBuMYCOAU7TJGQRqDeEl4+T+aIZNMB 9QBFUfKupy7XZ3H5rJTrYaXFPyYkdRGu5ODEHvwnpRiu+uD1UaTR57iyK5kjToGY mcK3nVad2X1foMOQW33jVAhxGJ+sz2YB/XgQuNnqpUFKktLQ8Es1CSgzB02GvW2b OBJiFCZybMKtBnTEVINYc/dcZ6uOUQ17BwKoR4szFGQLWrzbnfe7as5fa0uyj3ib BEbWcDM3KCDMRWAE/VwgyGzH3lg4QP1mE7uRdLfMb5JhIbQvHjo7T0bUBzUy5/Mf 4P9CWweplIi82Q0f2q7r =5hCV -----END PGP SIGNATURE----- Merge tag 'please-pull-for_5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras Pull EDAC updates from Tony Luck: "All the bits that Boris had queued in his tree plus four patches to add support for Intel Icelake Xeon and then fix a few corner cases" * tag 'please-pull-for_5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/ras/ras: EDAC: Fix global-out-of-bounds write when setting edac_mc_poll_msec EDAC, skx, i10nm: Fix source ID register offset EDAC, i10nm: Check ECC enabling status per channel EDAC, i10nm: Add Intel additional Ice-Lake support EDAC: Make edac_debugfs_create_x*() return void EDAC/aspeed: Remove set but not used variable 'np' EDAC/ie31200: Reformat PCI device table EDAC/ie31200: Add Intel Coffee Lake CPU support EDAC/sifive: Add EDAC platform driver for SiFive SoCs EDAC/sb_edac: Remove redundant update of tad_base arm64: dts: stratix10: Add SDMMC EDAC node EDAC/altera: Add Stratix10 SDMMC support arm64: dts: stratix10: Add OCRAM EDAC node EDAC/altera: Add Stratix10 OCRAM ECC support EDAC/sysfs: Drop device references properly EDAC/sysfs: Fix memory leak when creating a csrow object
This commit is contained in:
commit
947fbd4ca9
|
@ -5828,6 +5828,12 @@ L: linux-edac@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/edac/sb_edac.c
|
F: drivers/edac/sb_edac.c
|
||||||
|
|
||||||
|
EDAC-SIFIVE
|
||||||
|
M: Yash Shah <yash.shah@sifive.com>
|
||||||
|
L: linux-edac@vger.kernel.org
|
||||||
|
S: Supported
|
||||||
|
F: drivers/edac/sifive_edac.c
|
||||||
|
|
||||||
EDAC-SKYLAKE
|
EDAC-SKYLAKE
|
||||||
M: Tony Luck <tony.luck@intel.com>
|
M: Tony Luck <tony.luck@intel.com>
|
||||||
L: linux-edac@vger.kernel.org
|
L: linux-edac@vger.kernel.org
|
||||||
|
|
|
@ -539,6 +539,14 @@
|
||||||
interrupts = <16 4>;
|
interrupts = <16 4>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ocram-ecc@ff8cc000 {
|
||||||
|
compatible = "altr,socfpga-s10-ocram-ecc",
|
||||||
|
"altr,socfpga-a10-ocram-ecc";
|
||||||
|
reg = <0xff8cc000 0x100>;
|
||||||
|
altr,ecc-parent = <&ocram>;
|
||||||
|
interrupts = <1 4>;
|
||||||
|
};
|
||||||
|
|
||||||
usb0-ecc@ff8c4000 {
|
usb0-ecc@ff8c4000 {
|
||||||
compatible = "altr,socfpga-s10-usb-ecc",
|
compatible = "altr,socfpga-s10-usb-ecc",
|
||||||
"altr,socfpga-usb-ecc";
|
"altr,socfpga-usb-ecc";
|
||||||
|
|
|
@ -56,6 +56,17 @@
|
||||||
clock-frequency = <25000000>;
|
clock-frequency = <25000000>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
eccmgr {
|
||||||
|
sdmmca-ecc@ff8c8c00 {
|
||||||
|
compatible = "altr,socfpga-s10-sdmmc-ecc",
|
||||||
|
"altr,socfpga-sdmmc-ecc";
|
||||||
|
reg = <0xff8c8c00 0x100>;
|
||||||
|
altr,ecc-parent = <&mmc>;
|
||||||
|
interrupts = <14 4>,
|
||||||
|
<15 4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ config RISCV
|
||||||
select ARCH_HAS_PTE_SPECIAL
|
select ARCH_HAS_PTE_SPECIAL
|
||||||
select ARCH_HAS_MMIOWB
|
select ARCH_HAS_MMIOWB
|
||||||
select HAVE_EBPF_JIT if 64BIT
|
select HAVE_EBPF_JIT if 64BIT
|
||||||
|
select EDAC_SUPPORT
|
||||||
|
|
||||||
config MMU
|
config MMU
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
|
@ -460,6 +460,12 @@ config EDAC_ALTERA_SDMMC
|
||||||
Support for error detection and correction on the
|
Support for error detection and correction on the
|
||||||
Altera SDMMC FIFO Memory for Altera SoCs.
|
Altera SDMMC FIFO Memory for Altera SoCs.
|
||||||
|
|
||||||
|
config EDAC_SIFIVE
|
||||||
|
bool "Sifive platform EDAC driver"
|
||||||
|
depends on EDAC=y && RISCV
|
||||||
|
help
|
||||||
|
Support for error detection and correction on the SiFive SoCs.
|
||||||
|
|
||||||
config EDAC_SYNOPSYS
|
config EDAC_SYNOPSYS
|
||||||
tristate "Synopsys DDR Memory Controller"
|
tristate "Synopsys DDR Memory Controller"
|
||||||
depends on ARCH_ZYNQ || ARCH_ZYNQMP
|
depends on ARCH_ZYNQ || ARCH_ZYNQMP
|
||||||
|
|
|
@ -79,6 +79,7 @@ obj-$(CONFIG_EDAC_OCTEON_PCI) += octeon_edac-pci.o
|
||||||
obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o
|
obj-$(CONFIG_EDAC_THUNDERX) += thunderx_edac.o
|
||||||
|
|
||||||
obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o
|
obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o
|
||||||
|
obj-$(CONFIG_EDAC_SIFIVE) += sifive_edac.o
|
||||||
obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o
|
obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o
|
||||||
obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o
|
obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o
|
||||||
obj-$(CONFIG_EDAC_TI) += ti_edac.o
|
obj-$(CONFIG_EDAC_TI) += ti_edac.o
|
||||||
|
|
|
@ -1223,8 +1223,31 @@ static const struct edac_device_prv_data ocramecc_data = {
|
||||||
.inject_fops = &altr_edac_device_inject_fops,
|
.inject_fops = &altr_edac_device_inject_fops,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int __maybe_unused
|
||||||
|
altr_check_ocram_deps_init(struct altr_edac_device_dev *device)
|
||||||
|
{
|
||||||
|
void __iomem *base = device->base;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = altr_check_ecc_deps(device);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Verify OCRAM has been initialized */
|
||||||
|
if (!ecc_test_bits(ALTR_A10_ECC_INITCOMPLETEA,
|
||||||
|
(base + ALTR_A10_ECC_INITSTAT_OFST)))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
/* Enable IRQ on Single Bit Error */
|
||||||
|
writel(ALTR_A10_ECC_SERRINTEN, (base + ALTR_A10_ECC_ERRINTENS_OFST));
|
||||||
|
/* Ensure all writes complete */
|
||||||
|
wmb();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct edac_device_prv_data a10_ocramecc_data = {
|
static const struct edac_device_prv_data a10_ocramecc_data = {
|
||||||
.setup = altr_check_ecc_deps,
|
.setup = altr_check_ocram_deps_init,
|
||||||
.ce_clear_mask = ALTR_A10_ECC_SERRPENA,
|
.ce_clear_mask = ALTR_A10_ECC_SERRPENA,
|
||||||
.ue_clear_mask = ALTR_A10_ECC_DERRPENA,
|
.ue_clear_mask = ALTR_A10_ECC_DERRPENA,
|
||||||
.irq_status_mask = A10_SYSMGR_ECC_INTSTAT_OCRAM,
|
.irq_status_mask = A10_SYSMGR_ECC_INTSTAT_OCRAM,
|
||||||
|
@ -1234,7 +1257,7 @@ static const struct edac_device_prv_data a10_ocramecc_data = {
|
||||||
.ue_set_mask = ALTR_A10_ECC_TDERRA,
|
.ue_set_mask = ALTR_A10_ECC_TDERRA,
|
||||||
.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
|
.set_err_ofst = ALTR_A10_ECC_INTTEST_OFST,
|
||||||
.ecc_irq_handler = altr_edac_a10_ecc_irq,
|
.ecc_irq_handler = altr_edac_a10_ecc_irq,
|
||||||
.inject_fops = &altr_edac_a10_device_inject_fops,
|
.inject_fops = &altr_edac_a10_device_inject2_fops,
|
||||||
/*
|
/*
|
||||||
* OCRAM panic on uncorrectable error because sleep/resume
|
* OCRAM panic on uncorrectable error because sleep/resume
|
||||||
* functions and FPGA contents are stored in OCRAM. Prefer
|
* functions and FPGA contents are stored in OCRAM. Prefer
|
||||||
|
@ -1560,8 +1583,12 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
||||||
dci->mod_name = ecc_name;
|
dci->mod_name = ecc_name;
|
||||||
dci->dev_name = ecc_name;
|
dci->dev_name = ecc_name;
|
||||||
|
|
||||||
/* Update the IRQs for PortB */
|
/* Update the PortB IRQs - A10 has 4, S10 has 2, Index accordingly */
|
||||||
|
#ifdef CONFIG_ARCH_STRATIX10
|
||||||
|
altdev->sb_irq = irq_of_parse_and_map(np, 1);
|
||||||
|
#else
|
||||||
altdev->sb_irq = irq_of_parse_and_map(np, 2);
|
altdev->sb_irq = irq_of_parse_and_map(np, 2);
|
||||||
|
#endif
|
||||||
if (!altdev->sb_irq) {
|
if (!altdev->sb_irq) {
|
||||||
edac_printk(KERN_ERR, EDAC_DEVICE, "Error PortB SBIRQ alloc\n");
|
edac_printk(KERN_ERR, EDAC_DEVICE, "Error PortB SBIRQ alloc\n");
|
||||||
rc = -ENODEV;
|
rc = -ENODEV;
|
||||||
|
@ -1576,6 +1603,15 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
||||||
goto err_release_group_1;
|
goto err_release_group_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_STRATIX10
|
||||||
|
/* Use IRQ to determine SError origin instead of assigning IRQ */
|
||||||
|
rc = of_property_read_u32_index(np, "interrupts", 1, &altdev->db_irq);
|
||||||
|
if (rc) {
|
||||||
|
edac_printk(KERN_ERR, EDAC_DEVICE,
|
||||||
|
"Error PortB DBIRQ alloc\n");
|
||||||
|
goto err_release_group_1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
altdev->db_irq = irq_of_parse_and_map(np, 3);
|
altdev->db_irq = irq_of_parse_and_map(np, 3);
|
||||||
if (!altdev->db_irq) {
|
if (!altdev->db_irq) {
|
||||||
edac_printk(KERN_ERR, EDAC_DEVICE, "Error PortB DBIRQ alloc\n");
|
edac_printk(KERN_ERR, EDAC_DEVICE, "Error PortB DBIRQ alloc\n");
|
||||||
|
@ -1590,6 +1626,7 @@ static int altr_portb_setup(struct altr_edac_device_dev *device)
|
||||||
edac_printk(KERN_ERR, EDAC_DEVICE, "PortB DBERR IRQ error\n");
|
edac_printk(KERN_ERR, EDAC_DEVICE, "PortB DBERR IRQ error\n");
|
||||||
goto err_release_group_1;
|
goto err_release_group_1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rc = edac_device_add_device(dci);
|
rc = edac_device_add_device(dci);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
|
|
@ -281,15 +281,11 @@ static int aspeed_probe(struct platform_device *pdev)
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct edac_mc_layer layers[2];
|
struct edac_mc_layer layers[2];
|
||||||
struct mem_ctl_info *mci;
|
struct mem_ctl_info *mci;
|
||||||
struct device_node *np;
|
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
u32 reg04;
|
u32 reg04;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* setup regmap */
|
|
||||||
np = dev->of_node;
|
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
if (!res)
|
if (!res)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
|
@ -118,23 +118,23 @@ edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
|
||||||
EXPORT_SYMBOL_GPL(edac_debugfs_create_file);
|
EXPORT_SYMBOL_GPL(edac_debugfs_create_file);
|
||||||
|
|
||||||
/* Wrapper for debugfs_create_x8() */
|
/* Wrapper for debugfs_create_x8() */
|
||||||
struct dentry *edac_debugfs_create_x8(const char *name, umode_t mode,
|
void edac_debugfs_create_x8(const char *name, umode_t mode,
|
||||||
struct dentry *parent, u8 *value)
|
struct dentry *parent, u8 *value)
|
||||||
{
|
{
|
||||||
if (!parent)
|
if (!parent)
|
||||||
parent = edac_debugfs;
|
parent = edac_debugfs;
|
||||||
|
|
||||||
return debugfs_create_x8(name, mode, parent, value);
|
debugfs_create_x8(name, mode, parent, value);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(edac_debugfs_create_x8);
|
EXPORT_SYMBOL_GPL(edac_debugfs_create_x8);
|
||||||
|
|
||||||
/* Wrapper for debugfs_create_x16() */
|
/* Wrapper for debugfs_create_x16() */
|
||||||
struct dentry *edac_debugfs_create_x16(const char *name, umode_t mode,
|
void edac_debugfs_create_x16(const char *name, umode_t mode,
|
||||||
struct dentry *parent, u16 *value)
|
struct dentry *parent, u16 *value)
|
||||||
{
|
{
|
||||||
if (!parent)
|
if (!parent)
|
||||||
parent = edac_debugfs;
|
parent = edac_debugfs;
|
||||||
|
|
||||||
return debugfs_create_x16(name, mode, parent, value);
|
debugfs_create_x16(name, mode, parent, value);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(edac_debugfs_create_x16);
|
EXPORT_SYMBOL_GPL(edac_debugfs_create_x16);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
static int edac_mc_log_ue = 1;
|
static int edac_mc_log_ue = 1;
|
||||||
static int edac_mc_log_ce = 1;
|
static int edac_mc_log_ce = 1;
|
||||||
static int edac_mc_panic_on_ue;
|
static int edac_mc_panic_on_ue;
|
||||||
static int edac_mc_poll_msec = 1000;
|
static unsigned int edac_mc_poll_msec = 1000;
|
||||||
|
|
||||||
/* Getter functions for above */
|
/* Getter functions for above */
|
||||||
int edac_mc_get_log_ue(void)
|
int edac_mc_get_log_ue(void)
|
||||||
|
@ -45,30 +45,30 @@ int edac_mc_get_panic_on_ue(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this is temporary */
|
/* this is temporary */
|
||||||
int edac_mc_get_poll_msec(void)
|
unsigned int edac_mc_get_poll_msec(void)
|
||||||
{
|
{
|
||||||
return edac_mc_poll_msec;
|
return edac_mc_poll_msec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int edac_set_poll_msec(const char *val, const struct kernel_param *kp)
|
static int edac_set_poll_msec(const char *val, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
unsigned long l;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!val)
|
if (!val)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = kstrtoul(val, 0, &l);
|
ret = kstrtouint(val, 0, &i);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (l < 1000)
|
if (i < 1000)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*((unsigned long *)kp->arg) = l;
|
*((unsigned int *)kp->arg) = i;
|
||||||
|
|
||||||
/* notify edac_mc engine to reset the poll period */
|
/* notify edac_mc engine to reset the poll period */
|
||||||
edac_mc_reset_delay_period(l);
|
edac_mc_reset_delay_period(i);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ MODULE_PARM_DESC(edac_mc_log_ue,
|
||||||
module_param(edac_mc_log_ce, int, 0644);
|
module_param(edac_mc_log_ce, int, 0644);
|
||||||
MODULE_PARM_DESC(edac_mc_log_ce,
|
MODULE_PARM_DESC(edac_mc_log_ce,
|
||||||
"Log correctable error to console: 0=off 1=on");
|
"Log correctable error to console: 0=off 1=on");
|
||||||
module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_int,
|
module_param_call(edac_mc_poll_msec, edac_set_poll_msec, param_get_uint,
|
||||||
&edac_mc_poll_msec, 0644);
|
&edac_mc_poll_msec, 0644);
|
||||||
MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
|
MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds");
|
||||||
|
|
||||||
|
@ -404,6 +404,8 @@ static inline int nr_pages_per_csrow(struct csrow_info *csrow)
|
||||||
static int edac_create_csrow_object(struct mem_ctl_info *mci,
|
static int edac_create_csrow_object(struct mem_ctl_info *mci,
|
||||||
struct csrow_info *csrow, int index)
|
struct csrow_info *csrow, int index)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
csrow->dev.type = &csrow_attr_type;
|
csrow->dev.type = &csrow_attr_type;
|
||||||
csrow->dev.groups = csrow_dev_groups;
|
csrow->dev.groups = csrow_dev_groups;
|
||||||
device_initialize(&csrow->dev);
|
device_initialize(&csrow->dev);
|
||||||
|
@ -415,7 +417,11 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
|
||||||
edac_dbg(0, "creating (virtual) csrow node %s\n",
|
edac_dbg(0, "creating (virtual) csrow node %s\n",
|
||||||
dev_name(&csrow->dev));
|
dev_name(&csrow->dev));
|
||||||
|
|
||||||
return device_add(&csrow->dev);
|
err = device_add(&csrow->dev);
|
||||||
|
if (err)
|
||||||
|
put_device(&csrow->dev);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a CSROW object under specifed edac_mc_device */
|
/* Create a CSROW object under specifed edac_mc_device */
|
||||||
|
@ -443,7 +449,8 @@ error:
|
||||||
csrow = mci->csrows[i];
|
csrow = mci->csrows[i];
|
||||||
if (!nr_pages_per_csrow(csrow))
|
if (!nr_pages_per_csrow(csrow))
|
||||||
continue;
|
continue;
|
||||||
put_device(&mci->csrows[i]->dev);
|
|
||||||
|
device_del(&mci->csrows[i]->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
@ -645,9 +652,11 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci,
|
||||||
dev_set_drvdata(&dimm->dev, dimm);
|
dev_set_drvdata(&dimm->dev, dimm);
|
||||||
pm_runtime_forbid(&mci->dev);
|
pm_runtime_forbid(&mci->dev);
|
||||||
|
|
||||||
err = device_add(&dimm->dev);
|
err = device_add(&dimm->dev);
|
||||||
|
if (err)
|
||||||
|
put_device(&dimm->dev);
|
||||||
|
|
||||||
edac_dbg(0, "creating rank/dimm device %s\n", dev_name(&dimm->dev));
|
edac_dbg(0, "created rank/dimm device %s\n", dev_name(&dimm->dev));
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -928,6 +937,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
|
||||||
err = device_add(&mci->dev);
|
err = device_add(&mci->dev);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
|
edac_dbg(1, "failure: create device %s\n", dev_name(&mci->dev));
|
||||||
|
put_device(&mci->dev);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ extern int edac_mc_get_log_ue(void);
|
||||||
extern int edac_mc_get_log_ce(void);
|
extern int edac_mc_get_log_ce(void);
|
||||||
extern int edac_mc_get_panic_on_ue(void);
|
extern int edac_mc_get_panic_on_ue(void);
|
||||||
extern int edac_get_poll_msec(void);
|
extern int edac_get_poll_msec(void);
|
||||||
extern int edac_mc_get_poll_msec(void);
|
extern unsigned int edac_mc_get_poll_msec(void);
|
||||||
|
|
||||||
unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,
|
unsigned edac_dimm_info_location(struct dimm_info *dimm, char *buf,
|
||||||
unsigned len);
|
unsigned len);
|
||||||
|
@ -78,10 +78,10 @@ edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent);
|
||||||
struct dentry *
|
struct dentry *
|
||||||
edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
|
edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
|
||||||
void *data, const struct file_operations *fops);
|
void *data, const struct file_operations *fops);
|
||||||
struct dentry *
|
void edac_debugfs_create_x8(const char *name, umode_t mode,
|
||||||
edac_debugfs_create_x8(const char *name, umode_t mode, struct dentry *parent, u8 *value);
|
struct dentry *parent, u8 *value);
|
||||||
struct dentry *
|
void edac_debugfs_create_x16(const char *name, umode_t mode,
|
||||||
edac_debugfs_create_x16(const char *name, umode_t mode, struct dentry *parent, u16 *value);
|
struct dentry *parent, u16 *value);
|
||||||
#else
|
#else
|
||||||
static inline void edac_debugfs_init(void) { }
|
static inline void edac_debugfs_init(void) { }
|
||||||
static inline void edac_debugfs_exit(void) { }
|
static inline void edac_debugfs_exit(void) { }
|
||||||
|
@ -92,12 +92,10 @@ edac_debugfs_create_dir_at(const char *dirname, struct dentry *parent) { return
|
||||||
static inline struct dentry *
|
static inline struct dentry *
|
||||||
edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
|
edac_debugfs_create_file(const char *name, umode_t mode, struct dentry *parent,
|
||||||
void *data, const struct file_operations *fops) { return NULL; }
|
void *data, const struct file_operations *fops) { return NULL; }
|
||||||
static inline struct dentry *
|
static inline void edac_debugfs_create_x8(const char *name, umode_t mode,
|
||||||
edac_debugfs_create_x8(const char *name, umode_t mode,
|
struct dentry *parent, u8 *value) { }
|
||||||
struct dentry *parent, u8 *value) { return NULL; }
|
static inline void edac_debugfs_create_x16(const char *name, umode_t mode,
|
||||||
static inline struct dentry *
|
struct dentry *parent, u16 *value) { }
|
||||||
edac_debugfs_create_x16(const char *name, umode_t mode,
|
|
||||||
struct dentry *parent, u16 *value) { return NULL; }
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -124,6 +124,8 @@ static int i10nm_get_all_munits(void)
|
||||||
|
|
||||||
static const struct x86_cpu_id i10nm_cpuids[] = {
|
static const struct x86_cpu_id i10nm_cpuids[] = {
|
||||||
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_TREMONT_X, 0, 0 },
|
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_TREMONT_X, 0, 0 },
|
||||||
|
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_X, 0, 0 },
|
||||||
|
{ X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_XEON_D, 0, 0 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
|
MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
|
||||||
|
@ -166,9 +168,9 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
|
||||||
ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
|
ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
|
||||||
EDAC_MOD_STR);
|
EDAC_MOD_STR);
|
||||||
}
|
}
|
||||||
if (ndimms && !i10nm_check_ecc(imc, 0)) {
|
if (ndimms && !i10nm_check_ecc(imc, i)) {
|
||||||
i10nm_printk(KERN_ERR, "ECC is disabled on imc %d\n",
|
i10nm_printk(KERN_ERR, "ECC is disabled on imc %d channel %d\n",
|
||||||
imc->mc);
|
imc->mc, i);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,7 +267,7 @@ static int __init i10nm_init(void)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
list_for_each_entry(d, i10nm_edac_list, list) {
|
list_for_each_entry(d, i10nm_edac_list, list) {
|
||||||
rc = skx_get_src_id(d, &src_id);
|
rc = skx_get_src_id(d, 0xf8, &src_id);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,13 @@
|
||||||
* 0c08: Xeon E3-1200 v3 Processor DRAM Controller
|
* 0c08: Xeon E3-1200 v3 Processor DRAM Controller
|
||||||
* 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers
|
* 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers
|
||||||
* 5918: Xeon E3-1200 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
|
* 5918: Xeon E3-1200 Xeon E3-1200 v6/7th Gen Core Processor Host Bridge/DRAM Registers
|
||||||
|
* 3e..: 8th/9th Gen Core Processor Host Bridge/DRAM Registers
|
||||||
*
|
*
|
||||||
* Based on Intel specification:
|
* Based on Intel specification:
|
||||||
* http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
|
* http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf
|
||||||
* http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html
|
* http://www.intel.com/content/www/us/en/processors/xeon/xeon-e3-1200-family-vol-2-datasheet.html
|
||||||
* http://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html
|
* http://www.intel.com/content/www/us/en/processors/core/7th-gen-core-family-mobile-h-processor-lines-datasheet-vol-2.html
|
||||||
|
* https://www.intel.com/content/www/us/en/products/docs/processors/core/8th-gen-core-family-datasheet-vol-2.html
|
||||||
*
|
*
|
||||||
* According to the above datasheet (p.16):
|
* According to the above datasheet (p.16):
|
||||||
* "
|
* "
|
||||||
|
@ -61,6 +63,26 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918
|
||||||
#define PCI_DEVICE_ID_INTEL_IE31200_HB_9 0x5918
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_9 0x5918
|
||||||
|
|
||||||
|
/* Coffee Lake-S */
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK 0x3e00
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_1 0x3e0f
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_2 0x3e18
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_3 0x3e1f
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_4 0x3e30
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_5 0x3e31
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_6 0x3e32
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_7 0x3e33
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_8 0x3ec2
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_9 0x3ec6
|
||||||
|
#define PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_10 0x3eca
|
||||||
|
|
||||||
|
/* Test if HB is for Skylake or later. */
|
||||||
|
#define DEVICE_ID_SKYLAKE_OR_LATER(did) \
|
||||||
|
(((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_8) || \
|
||||||
|
((did) == PCI_DEVICE_ID_INTEL_IE31200_HB_9) || \
|
||||||
|
(((did) & PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK) == \
|
||||||
|
PCI_DEVICE_ID_INTEL_IE31200_HB_CFL_MASK))
|
||||||
|
|
||||||
#define IE31200_DIMMS 4
|
#define IE31200_DIMMS 4
|
||||||
#define IE31200_RANKS 8
|
#define IE31200_RANKS 8
|
||||||
#define IE31200_RANKS_PER_CHANNEL 4
|
#define IE31200_RANKS_PER_CHANNEL 4
|
||||||
|
@ -381,10 +403,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
|
||||||
u32 addr_decode, mad_offset;
|
u32 addr_decode, mad_offset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kaby Lake seems to work like Skylake. Please re-visit this logic
|
* Kaby Lake, Coffee Lake seem to work like Skylake. Please re-visit
|
||||||
* when adding new CPU support.
|
* this logic when adding new CPU support.
|
||||||
*/
|
*/
|
||||||
bool skl = (pdev->device >= PCI_DEVICE_ID_INTEL_IE31200_HB_8);
|
bool skl = DEVICE_ID_SKYLAKE_OR_LATER(pdev->device);
|
||||||
|
|
||||||
edac_dbg(0, "MC:\n");
|
edac_dbg(0, "MC:\n");
|
||||||
|
|
||||||
|
@ -542,36 +564,26 @@ static void ie31200_remove_one(struct pci_dev *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pci_device_id ie31200_pci_tbl[] = {
|
static const struct pci_device_id ie31200_pci_tbl[] = {
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_1), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_1), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_2), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
IE31200},
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_3), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_4), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_2), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_5), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
IE31200},
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_6), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_3), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
IE31200},
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_1), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_4), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_2), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
IE31200},
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_3), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_4), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_5), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_5), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
IE31200},
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_6), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_6), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
IE31200},
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
{
|
{ PCI_VEND_DEV(INTEL, IE31200_HB_CFL_10), PCI_ANY_ID, PCI_ANY_ID, 0, 0, IE31200 },
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
{ 0, } /* 0 terminated list. */
|
||||||
IE31200},
|
|
||||||
{
|
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
IE31200},
|
|
||||||
{
|
|
||||||
PCI_VEND_DEV(INTEL, IE31200_HB_9), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
||||||
IE31200},
|
|
||||||
{
|
|
||||||
0,
|
|
||||||
} /* 0 terminated list. */
|
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, ie31200_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, ie31200_pci_tbl);
|
||||||
|
|
||||||
|
|
|
@ -1511,7 +1511,6 @@ static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
|
||||||
sad_actual_size[mc] += tad_size;
|
sad_actual_size[mc] += tad_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tad_base = tad_limit+1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
119
drivers/edac/sifive_edac.c
Normal file
119
drivers/edac/sifive_edac.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* SiFive Platform EDAC Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018-2019 SiFive, Inc.
|
||||||
|
*
|
||||||
|
* This driver is partially based on octeon_edac-pc.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#include <linux/edac.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include "edac_module.h"
|
||||||
|
#include <asm/sifive_l2_cache.h>
|
||||||
|
|
||||||
|
#define DRVNAME "sifive_edac"
|
||||||
|
|
||||||
|
struct sifive_edac_priv {
|
||||||
|
struct notifier_block notifier;
|
||||||
|
struct edac_device_ctl_info *dci;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EDAC error callback
|
||||||
|
*
|
||||||
|
* @event: non-zero if unrecoverable.
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
int ecc_err_event(struct notifier_block *this, unsigned long event, void *ptr)
|
||||||
|
{
|
||||||
|
const char *msg = (char *)ptr;
|
||||||
|
struct sifive_edac_priv *p;
|
||||||
|
|
||||||
|
p = container_of(this, struct sifive_edac_priv, notifier);
|
||||||
|
|
||||||
|
if (event == SIFIVE_L2_ERR_TYPE_UE)
|
||||||
|
edac_device_handle_ue(p->dci, 0, 0, msg);
|
||||||
|
else if (event == SIFIVE_L2_ERR_TYPE_CE)
|
||||||
|
edac_device_handle_ce(p->dci, 0, 0, msg);
|
||||||
|
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ecc_register(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct sifive_edac_priv *p;
|
||||||
|
|
||||||
|
p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
p->notifier.notifier_call = ecc_err_event;
|
||||||
|
platform_set_drvdata(pdev, p);
|
||||||
|
|
||||||
|
p->dci = edac_device_alloc_ctl_info(0, "sifive_ecc", 1, "sifive_ecc",
|
||||||
|
1, 1, NULL, 0,
|
||||||
|
edac_device_alloc_index());
|
||||||
|
if (IS_ERR(p->dci))
|
||||||
|
return PTR_ERR(p->dci);
|
||||||
|
|
||||||
|
p->dci->dev = &pdev->dev;
|
||||||
|
p->dci->mod_name = "Sifive ECC Manager";
|
||||||
|
p->dci->ctl_name = dev_name(&pdev->dev);
|
||||||
|
p->dci->dev_name = dev_name(&pdev->dev);
|
||||||
|
|
||||||
|
if (edac_device_add_device(p->dci)) {
|
||||||
|
dev_err(p->dci->dev, "failed to register with EDAC core\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_sifive_l2_error_notifier(&p->notifier);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
edac_device_free_ctl_info(p->dci);
|
||||||
|
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ecc_unregister(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct sifive_edac_priv *p = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
unregister_sifive_l2_error_notifier(&p->notifier);
|
||||||
|
edac_device_del_device(&pdev->dev);
|
||||||
|
edac_device_free_ctl_info(p->dci);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_device *sifive_pdev;
|
||||||
|
|
||||||
|
static int __init sifive_edac_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
sifive_pdev = platform_device_register_simple(DRVNAME, 0, NULL, 0);
|
||||||
|
if (IS_ERR(sifive_pdev))
|
||||||
|
return PTR_ERR(sifive_pdev);
|
||||||
|
|
||||||
|
ret = ecc_register(sifive_pdev);
|
||||||
|
if (ret)
|
||||||
|
platform_device_unregister(sifive_pdev);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit sifive_edac_exit(void)
|
||||||
|
{
|
||||||
|
ecc_unregister(sifive_pdev);
|
||||||
|
platform_device_unregister(sifive_pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(sifive_edac_init);
|
||||||
|
module_exit(sifive_edac_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("SiFive Inc.");
|
||||||
|
MODULE_DESCRIPTION("SiFive platform EDAC driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
|
@ -639,7 +639,7 @@ static int __init skx_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(d, skx_edac_list, list) {
|
list_for_each_entry(d, skx_edac_list, list) {
|
||||||
rc = skx_get_src_id(d, &src_id);
|
rc = skx_get_src_id(d, 0xf0, &src_id);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
rc = skx_get_node_id(d, &node_id);
|
rc = skx_get_node_id(d, &node_id);
|
||||||
|
|
|
@ -136,11 +136,11 @@ void skx_set_decode(skx_decode_f decode)
|
||||||
skx_decode = decode;
|
skx_decode = decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int skx_get_src_id(struct skx_dev *d, u8 *id)
|
int skx_get_src_id(struct skx_dev *d, int off, u8 *id)
|
||||||
{
|
{
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
|
||||||
if (pci_read_config_dword(d->util_all, 0xf0, ®)) {
|
if (pci_read_config_dword(d->util_all, off, ®)) {
|
||||||
skx_printk(KERN_ERR, "Failed to read src id\n");
|
skx_printk(KERN_ERR, "Failed to read src id\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ int __init skx_adxl_get(void);
|
||||||
void __exit skx_adxl_put(void);
|
void __exit skx_adxl_put(void);
|
||||||
void skx_set_decode(skx_decode_f decode);
|
void skx_set_decode(skx_decode_f decode);
|
||||||
|
|
||||||
int skx_get_src_id(struct skx_dev *d, u8 *id);
|
int skx_get_src_id(struct skx_dev *d, int off, u8 *id);
|
||||||
int skx_get_node_id(struct skx_dev *d, u8 *id);
|
int skx_get_node_id(struct skx_dev *d, u8 *id);
|
||||||
|
|
||||||
int skx_get_all_bus_mappings(unsigned int did, int off, enum type,
|
int skx_get_all_bus_mappings(unsigned int did, int off, enum type,
|
||||||
|
|
Loading…
Reference in a new issue