Commit c1c2ad82 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'edac_for_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp

Pull EDAC updates from Borislav Petkov:

 - Add support for systems with PCI segmented buses to sb_edac, by
   Masayoshi Mizuma

 - The usual pile of fixes and cleanups

* tag 'edac_for_4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  EDAC, sb_edac: Add support for systems with segmented PCI buses
  EDAC, thunderx: Remove VLA usage
  EDAC, i7core: Fix memleaks and use-after-free on probe and remove
  EDAC: Fix memleak in module init error path
  EDAC, altera: Fix an error handling path in altr_s10_sdram_probe()
parents 99a2c789 190bd6e9
...@@ -730,7 +730,8 @@ static int altr_s10_sdram_probe(struct platform_device *pdev) ...@@ -730,7 +730,8 @@ static int altr_s10_sdram_probe(struct platform_device *pdev)
S10_DDR0_IRQ_MASK)) { S10_DDR0_IRQ_MASK)) {
edac_printk(KERN_ERR, EDAC_MC, edac_printk(KERN_ERR, EDAC_MC,
"Error clearing SDRAM ECC count\n"); "Error clearing SDRAM ECC count\n");
return -ENODEV; ret = -ENODEV;
goto err2;
} }
if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset, if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset,
......
...@@ -1075,14 +1075,14 @@ int __init edac_mc_sysfs_init(void) ...@@ -1075,14 +1075,14 @@ int __init edac_mc_sysfs_init(void)
err = device_add(mci_pdev); err = device_add(mci_pdev);
if (err < 0) if (err < 0)
goto out_dev_free; goto out_put_device;
edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); edac_dbg(0, "device %s created\n", dev_name(mci_pdev));
return 0; return 0;
out_dev_free: out_put_device:
kfree(mci_pdev); put_device(mci_pdev);
out: out:
return err; return err;
} }
......
...@@ -1177,15 +1177,14 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) ...@@ -1177,15 +1177,14 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
rc = device_add(pvt->addrmatch_dev); rc = device_add(pvt->addrmatch_dev);
if (rc < 0) if (rc < 0)
return rc; goto err_put_addrmatch;
if (!pvt->is_registered) { if (!pvt->is_registered) {
pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev),
GFP_KERNEL); GFP_KERNEL);
if (!pvt->chancounts_dev) { if (!pvt->chancounts_dev) {
put_device(pvt->addrmatch_dev); rc = -ENOMEM;
device_del(pvt->addrmatch_dev); goto err_del_addrmatch;
return -ENOMEM;
} }
pvt->chancounts_dev->type = &all_channel_counts_type; pvt->chancounts_dev->type = &all_channel_counts_type;
...@@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) ...@@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
rc = device_add(pvt->chancounts_dev); rc = device_add(pvt->chancounts_dev);
if (rc < 0) if (rc < 0)
return rc; goto err_put_chancounts;
} }
return 0; return 0;
err_put_chancounts:
put_device(pvt->chancounts_dev);
err_del_addrmatch:
device_del(pvt->addrmatch_dev);
err_put_addrmatch:
put_device(pvt->addrmatch_dev);
return rc;
} }
static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci)
...@@ -1211,11 +1219,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) ...@@ -1211,11 +1219,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci)
edac_dbg(1, "\n"); edac_dbg(1, "\n");
if (!pvt->is_registered) { if (!pvt->is_registered) {
put_device(pvt->chancounts_dev);
device_del(pvt->chancounts_dev); device_del(pvt->chancounts_dev);
put_device(pvt->chancounts_dev);
} }
put_device(pvt->addrmatch_dev);
device_del(pvt->addrmatch_dev); device_del(pvt->addrmatch_dev);
put_device(pvt->addrmatch_dev);
} }
/**************************************************************************** /****************************************************************************
......
...@@ -352,6 +352,7 @@ struct pci_id_table { ...@@ -352,6 +352,7 @@ struct pci_id_table {
struct sbridge_dev { struct sbridge_dev {
struct list_head list; struct list_head list;
int seg;
u8 bus, mc; u8 bus, mc;
u8 node_id, source_id; u8 node_id, source_id;
struct pci_dev **pdev; struct pci_dev **pdev;
...@@ -729,7 +730,8 @@ static inline int numcol(u32 mtr) ...@@ -729,7 +730,8 @@ static inline int numcol(u32 mtr)
return 1 << cols; return 1 << cols;
} }
static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bus, static struct sbridge_dev *get_sbridge_dev(int seg, u8 bus, enum domain dom,
int multi_bus,
struct sbridge_dev *prev) struct sbridge_dev *prev)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
...@@ -747,14 +749,15 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bu ...@@ -747,14 +749,15 @@ static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bu
: sbridge_edac_list.next, struct sbridge_dev, list); : sbridge_edac_list.next, struct sbridge_dev, list);
list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) { list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) {
if (sbridge_dev->bus == bus && (dom == SOCK || dom == sbridge_dev->dom)) if ((sbridge_dev->seg == seg) && (sbridge_dev->bus == bus) &&
(dom == SOCK || dom == sbridge_dev->dom))
return sbridge_dev; return sbridge_dev;
} }
return NULL; return NULL;
} }
static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, static struct sbridge_dev *alloc_sbridge_dev(int seg, u8 bus, enum domain dom,
const struct pci_id_table *table) const struct pci_id_table *table)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
...@@ -771,6 +774,7 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, ...@@ -771,6 +774,7 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom,
return NULL; return NULL;
} }
sbridge_dev->seg = seg;
sbridge_dev->bus = bus; sbridge_dev->bus = bus;
sbridge_dev->dom = dom; sbridge_dev->dom = dom;
sbridge_dev->n_devs = table->n_devs_per_imc; sbridge_dev->n_devs = table->n_devs_per_imc;
...@@ -2246,6 +2250,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2246,6 +2250,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
struct sbridge_dev *sbridge_dev = NULL; struct sbridge_dev *sbridge_dev = NULL;
const struct pci_id_descr *dev_descr = &table->descr[devno]; const struct pci_id_descr *dev_descr = &table->descr[devno];
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
int seg = 0;
u8 bus = 0; u8 bus = 0;
int i = 0; int i = 0;
...@@ -2276,10 +2281,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2276,10 +2281,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
/* End of list, leave */ /* End of list, leave */
return -ENODEV; return -ENODEV;
} }
seg = pci_domain_nr(pdev->bus);
bus = pdev->bus->number; bus = pdev->bus->number;
next_imc: next_imc:
sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); sbridge_dev = get_sbridge_dev(seg, bus, dev_descr->dom,
multi_bus, sbridge_dev);
if (!sbridge_dev) { if (!sbridge_dev) {
/* If the HA1 wasn't found, don't create EDAC second memory controller */ /* If the HA1 wasn't found, don't create EDAC second memory controller */
if (dev_descr->dom == IMC1 && devno != 1) { if (dev_descr->dom == IMC1 && devno != 1) {
...@@ -2292,7 +2299,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -2292,7 +2299,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
if (dev_descr->dom == SOCK) if (dev_descr->dom == SOCK)
goto out_imc; goto out_imc;
sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table); sbridge_dev = alloc_sbridge_dev(seg, bus, dev_descr->dom, table);
if (!sbridge_dev) { if (!sbridge_dev) {
pci_dev_put(pdev); pci_dev_put(pdev);
return -ENOMEM; return -ENOMEM;
......
...@@ -408,26 +408,29 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, ...@@ -408,26 +408,29 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct thunderx_lmc *lmc = file->private_data; struct thunderx_lmc *lmc = file->private_data;
unsigned int cline_size = cache_line_size(); unsigned int cline_size = cache_line_size();
u8 *tmp;
u8 tmp[cline_size];
void __iomem *addr; void __iomem *addr;
unsigned int offs, timeout = 100000; unsigned int offs, timeout = 100000;
atomic_set(&lmc->ecc_int, 0); atomic_set(&lmc->ecc_int, 0);
lmc->mem = alloc_pages_node(lmc->node, GFP_KERNEL, 0); lmc->mem = alloc_pages_node(lmc->node, GFP_KERNEL, 0);
if (!lmc->mem) if (!lmc->mem)
return -ENOMEM; return -ENOMEM;
tmp = kmalloc(cline_size, GFP_KERNEL);
if (!tmp) {
__free_pages(lmc->mem, 0);
return -ENOMEM;
}
addr = page_address(lmc->mem); addr = page_address(lmc->mem);
while (!atomic_read(&lmc->ecc_int) && timeout--) { while (!atomic_read(&lmc->ecc_int) && timeout--) {
stop_machine(inject_ecc_fn, lmc, NULL); stop_machine(inject_ecc_fn, lmc, NULL);
for (offs = 0; offs < PAGE_SIZE; offs += sizeof(tmp)) { for (offs = 0; offs < PAGE_SIZE; offs += cline_size) {
/* /*
* Do a load from the previously rigged location * Do a load from the previously rigged location
* This should generate an error interrupt. * This should generate an error interrupt.
...@@ -437,6 +440,7 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, ...@@ -437,6 +440,7 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file,
} }
} }
kfree(tmp);
__free_pages(lmc->mem, 0); __free_pages(lmc->mem, 0);
return count; return count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment