diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-15 21:31:19 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-15 21:31:19 -0700 |
commit | c1c2ad82c772966d3cdb9a4852329fa2cf71853a (patch) | |
tree | 1296ea11754303d3a2cdf5c157984e8aae509e9f | |
parent | 99a2c789ddeb703cf7b0a3d889ab1a25cf4cbbaf (diff) | |
parent | 190bd6e98afc512fb16d4a471acd488e36141637 (diff) | |
download | lwn-c1c2ad82c772966d3cdb9a4852329fa2cf71853a.tar.gz lwn-c1c2ad82c772966d3cdb9a4852329fa2cf71853a.zip |
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()
-rw-r--r-- | drivers/edac/altera_edac.c | 3 | ||||
-rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 6 | ||||
-rw-r--r-- | drivers/edac/i7core_edac.c | 22 | ||||
-rw-r--r-- | drivers/edac/sb_edac.c | 17 | ||||
-rw-r--r-- | drivers/edac/thunderx_edac.c | 14 |
5 files changed, 41 insertions, 21 deletions
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index d0d5c4dbe097..5762c3c383f2 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -730,7 +730,8 @@ static int altr_s10_sdram_probe(struct platform_device *pdev) S10_DDR0_IRQ_MASK)) { edac_printk(KERN_ERR, EDAC_MC, "Error clearing SDRAM ECC count\n"); - return -ENODEV; + ret = -ENODEV; + goto err2; } if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset, diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 7481955160a4..20374b8248f0 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c @@ -1075,14 +1075,14 @@ int __init edac_mc_sysfs_init(void) err = device_add(mci_pdev); if (err < 0) - goto out_dev_free; + goto out_put_device; edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); return 0; - out_dev_free: - kfree(mci_pdev); + out_put_device: + put_device(mci_pdev); out: return err; } diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 8ed4dd9c571b..8e120bf60624 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1177,15 +1177,14 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) rc = device_add(pvt->addrmatch_dev); if (rc < 0) - return rc; + goto err_put_addrmatch; if (!pvt->is_registered) { pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), GFP_KERNEL); if (!pvt->chancounts_dev) { - put_device(pvt->addrmatch_dev); - device_del(pvt->addrmatch_dev); - return -ENOMEM; + rc = -ENOMEM; + goto err_del_addrmatch; } pvt->chancounts_dev->type = &all_channel_counts_type; @@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) rc = device_add(pvt->chancounts_dev); if (rc < 0) - return rc; + goto err_put_chancounts; } 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) @@ -1211,11 +1219,11 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) edac_dbg(1, "\n"); if (!pvt->is_registered) { - put_device(pvt->chancounts_dev); device_del(pvt->chancounts_dev); + put_device(pvt->chancounts_dev); } - put_device(pvt->addrmatch_dev); device_del(pvt->addrmatch_dev); + put_device(pvt->addrmatch_dev); } /**************************************************************************** diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 4a89c8093307..07726fb00321 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -352,6 +352,7 @@ struct pci_id_table { struct sbridge_dev { struct list_head list; + int seg; u8 bus, mc; u8 node_id, source_id; struct pci_dev **pdev; @@ -729,7 +730,8 @@ static inline int numcol(u32 mtr) 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 *sbridge_dev; @@ -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); 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 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) { struct sbridge_dev *sbridge_dev; @@ -771,6 +774,7 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, return NULL; } + sbridge_dev->seg = seg; sbridge_dev->bus = bus; sbridge_dev->dom = dom; sbridge_dev->n_devs = table->n_devs_per_imc; @@ -2246,6 +2250,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, struct sbridge_dev *sbridge_dev = NULL; const struct pci_id_descr *dev_descr = &table->descr[devno]; struct pci_dev *pdev = NULL; + int seg = 0; u8 bus = 0; int i = 0; @@ -2276,10 +2281,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, /* End of list, leave */ return -ENODEV; } + seg = pci_domain_nr(pdev->bus); bus = pdev->bus->number; 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 the HA1 wasn't found, don't create EDAC second memory controller */ if (dev_descr->dom == IMC1 && devno != 1) { @@ -2292,7 +2299,7 @@ next_imc: if (dev_descr->dom == SOCK) 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) { pci_dev_put(pdev); return -ENOMEM; diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c index 4803c6468bab..c009d94f40c5 100644 --- a/drivers/edac/thunderx_edac.c +++ b/drivers/edac/thunderx_edac.c @@ -408,26 +408,29 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, size_t count, loff_t *ppos) { struct thunderx_lmc *lmc = file->private_data; - unsigned int cline_size = cache_line_size(); - - u8 tmp[cline_size]; + u8 *tmp; void __iomem *addr; unsigned int offs, timeout = 100000; atomic_set(&lmc->ecc_int, 0); lmc->mem = alloc_pages_node(lmc->node, GFP_KERNEL, 0); - if (!lmc->mem) return -ENOMEM; + tmp = kmalloc(cline_size, GFP_KERNEL); + if (!tmp) { + __free_pages(lmc->mem, 0); + return -ENOMEM; + } + addr = page_address(lmc->mem); while (!atomic_read(&lmc->ecc_int) && timeout--) { 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 * This should generate an error interrupt. @@ -437,6 +440,7 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, } } + kfree(tmp); __free_pages(lmc->mem, 0); return count; |