diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-16 00:31:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-16 00:31:19 -0400 |
commit | c1c2ad82c772966d3cdb9a4852329fa2cf71853a (patch) | |
tree | 1296ea11754303d3a2cdf5c157984e8aae509e9f | |
parent | 99a2c789ddeb703cf7b0a3d889ab1a25cf4cbbaf (diff) | |
parent | 190bd6e98afc512fb16d4a471acd488e36141637 (diff) |
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) | |||
730 | S10_DDR0_IRQ_MASK)) { | 730 | S10_DDR0_IRQ_MASK)) { |
731 | edac_printk(KERN_ERR, EDAC_MC, | 731 | edac_printk(KERN_ERR, EDAC_MC, |
732 | "Error clearing SDRAM ECC count\n"); | 732 | "Error clearing SDRAM ECC count\n"); |
733 | return -ENODEV; | 733 | ret = -ENODEV; |
734 | goto err2; | ||
734 | } | 735 | } |
735 | 736 | ||
736 | if (regmap_update_bits(drvdata->mc_vbase, priv->ecc_irq_en_offset, | 737 | 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) | |||
1075 | 1075 | ||
1076 | err = device_add(mci_pdev); | 1076 | err = device_add(mci_pdev); |
1077 | if (err < 0) | 1077 | if (err < 0) |
1078 | goto out_dev_free; | 1078 | goto out_put_device; |
1079 | 1079 | ||
1080 | edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); | 1080 | edac_dbg(0, "device %s created\n", dev_name(mci_pdev)); |
1081 | 1081 | ||
1082 | return 0; | 1082 | return 0; |
1083 | 1083 | ||
1084 | out_dev_free: | 1084 | out_put_device: |
1085 | kfree(mci_pdev); | 1085 | put_device(mci_pdev); |
1086 | out: | 1086 | out: |
1087 | return err; | 1087 | return err; |
1088 | } | 1088 | } |
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) | |||
1177 | 1177 | ||
1178 | rc = device_add(pvt->addrmatch_dev); | 1178 | rc = device_add(pvt->addrmatch_dev); |
1179 | if (rc < 0) | 1179 | if (rc < 0) |
1180 | return rc; | 1180 | goto err_put_addrmatch; |
1181 | 1181 | ||
1182 | if (!pvt->is_registered) { | 1182 | if (!pvt->is_registered) { |
1183 | pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), | 1183 | pvt->chancounts_dev = kzalloc(sizeof(*pvt->chancounts_dev), |
1184 | GFP_KERNEL); | 1184 | GFP_KERNEL); |
1185 | if (!pvt->chancounts_dev) { | 1185 | if (!pvt->chancounts_dev) { |
1186 | put_device(pvt->addrmatch_dev); | 1186 | rc = -ENOMEM; |
1187 | device_del(pvt->addrmatch_dev); | 1187 | goto err_del_addrmatch; |
1188 | return -ENOMEM; | ||
1189 | } | 1188 | } |
1190 | 1189 | ||
1191 | pvt->chancounts_dev->type = &all_channel_counts_type; | 1190 | pvt->chancounts_dev->type = &all_channel_counts_type; |
@@ -1199,9 +1198,18 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci) | |||
1199 | 1198 | ||
1200 | rc = device_add(pvt->chancounts_dev); | 1199 | rc = device_add(pvt->chancounts_dev); |
1201 | if (rc < 0) | 1200 | if (rc < 0) |
1202 | return rc; | 1201 | goto err_put_chancounts; |
1203 | } | 1202 | } |
1204 | return 0; | 1203 | return 0; |
1204 | |||
1205 | err_put_chancounts: | ||
1206 | put_device(pvt->chancounts_dev); | ||
1207 | err_del_addrmatch: | ||
1208 | device_del(pvt->addrmatch_dev); | ||
1209 | err_put_addrmatch: | ||
1210 | put_device(pvt->addrmatch_dev); | ||
1211 | |||
1212 | return rc; | ||
1205 | } | 1213 | } |
1206 | 1214 | ||
1207 | static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci) | 1215 | 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 | edac_dbg(1, "\n"); | 1219 | edac_dbg(1, "\n"); |
1212 | 1220 | ||
1213 | if (!pvt->is_registered) { | 1221 | if (!pvt->is_registered) { |
1214 | put_device(pvt->chancounts_dev); | ||
1215 | device_del(pvt->chancounts_dev); | 1222 | device_del(pvt->chancounts_dev); |
1223 | put_device(pvt->chancounts_dev); | ||
1216 | } | 1224 | } |
1217 | put_device(pvt->addrmatch_dev); | ||
1218 | device_del(pvt->addrmatch_dev); | 1225 | device_del(pvt->addrmatch_dev); |
1226 | put_device(pvt->addrmatch_dev); | ||
1219 | } | 1227 | } |
1220 | 1228 | ||
1221 | /**************************************************************************** | 1229 | /**************************************************************************** |
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 { | |||
352 | 352 | ||
353 | struct sbridge_dev { | 353 | struct sbridge_dev { |
354 | struct list_head list; | 354 | struct list_head list; |
355 | int seg; | ||
355 | u8 bus, mc; | 356 | u8 bus, mc; |
356 | u8 node_id, source_id; | 357 | u8 node_id, source_id; |
357 | struct pci_dev **pdev; | 358 | struct pci_dev **pdev; |
@@ -729,7 +730,8 @@ static inline int numcol(u32 mtr) | |||
729 | return 1 << cols; | 730 | return 1 << cols; |
730 | } | 731 | } |
731 | 732 | ||
732 | static struct sbridge_dev *get_sbridge_dev(u8 bus, enum domain dom, int multi_bus, | 733 | static struct sbridge_dev *get_sbridge_dev(int seg, u8 bus, enum domain dom, |
734 | int multi_bus, | ||
733 | struct sbridge_dev *prev) | 735 | struct sbridge_dev *prev) |
734 | { | 736 | { |
735 | struct sbridge_dev *sbridge_dev; | 737 | 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 | : sbridge_edac_list.next, struct sbridge_dev, list); | 749 | : sbridge_edac_list.next, struct sbridge_dev, list); |
748 | 750 | ||
749 | list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) { | 751 | list_for_each_entry_from(sbridge_dev, &sbridge_edac_list, list) { |
750 | if (sbridge_dev->bus == bus && (dom == SOCK || dom == sbridge_dev->dom)) | 752 | if ((sbridge_dev->seg == seg) && (sbridge_dev->bus == bus) && |
753 | (dom == SOCK || dom == sbridge_dev->dom)) | ||
751 | return sbridge_dev; | 754 | return sbridge_dev; |
752 | } | 755 | } |
753 | 756 | ||
754 | return NULL; | 757 | return NULL; |
755 | } | 758 | } |
756 | 759 | ||
757 | static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, | 760 | static struct sbridge_dev *alloc_sbridge_dev(int seg, u8 bus, enum domain dom, |
758 | const struct pci_id_table *table) | 761 | const struct pci_id_table *table) |
759 | { | 762 | { |
760 | struct sbridge_dev *sbridge_dev; | 763 | struct sbridge_dev *sbridge_dev; |
@@ -771,6 +774,7 @@ static struct sbridge_dev *alloc_sbridge_dev(u8 bus, enum domain dom, | |||
771 | return NULL; | 774 | return NULL; |
772 | } | 775 | } |
773 | 776 | ||
777 | sbridge_dev->seg = seg; | ||
774 | sbridge_dev->bus = bus; | 778 | sbridge_dev->bus = bus; |
775 | sbridge_dev->dom = dom; | 779 | sbridge_dev->dom = dom; |
776 | sbridge_dev->n_devs = table->n_devs_per_imc; | 780 | sbridge_dev->n_devs = table->n_devs_per_imc; |
@@ -2246,6 +2250,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
2246 | struct sbridge_dev *sbridge_dev = NULL; | 2250 | struct sbridge_dev *sbridge_dev = NULL; |
2247 | const struct pci_id_descr *dev_descr = &table->descr[devno]; | 2251 | const struct pci_id_descr *dev_descr = &table->descr[devno]; |
2248 | struct pci_dev *pdev = NULL; | 2252 | struct pci_dev *pdev = NULL; |
2253 | int seg = 0; | ||
2249 | u8 bus = 0; | 2254 | u8 bus = 0; |
2250 | int i = 0; | 2255 | int i = 0; |
2251 | 2256 | ||
@@ -2276,10 +2281,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev, | |||
2276 | /* End of list, leave */ | 2281 | /* End of list, leave */ |
2277 | return -ENODEV; | 2282 | return -ENODEV; |
2278 | } | 2283 | } |
2284 | seg = pci_domain_nr(pdev->bus); | ||
2279 | bus = pdev->bus->number; | 2285 | bus = pdev->bus->number; |
2280 | 2286 | ||
2281 | next_imc: | 2287 | next_imc: |
2282 | sbridge_dev = get_sbridge_dev(bus, dev_descr->dom, multi_bus, sbridge_dev); | 2288 | sbridge_dev = get_sbridge_dev(seg, bus, dev_descr->dom, |
2289 | multi_bus, sbridge_dev); | ||
2283 | if (!sbridge_dev) { | 2290 | if (!sbridge_dev) { |
2284 | /* If the HA1 wasn't found, don't create EDAC second memory controller */ | 2291 | /* If the HA1 wasn't found, don't create EDAC second memory controller */ |
2285 | if (dev_descr->dom == IMC1 && devno != 1) { | 2292 | if (dev_descr->dom == IMC1 && devno != 1) { |
@@ -2292,7 +2299,7 @@ next_imc: | |||
2292 | if (dev_descr->dom == SOCK) | 2299 | if (dev_descr->dom == SOCK) |
2293 | goto out_imc; | 2300 | goto out_imc; |
2294 | 2301 | ||
2295 | sbridge_dev = alloc_sbridge_dev(bus, dev_descr->dom, table); | 2302 | sbridge_dev = alloc_sbridge_dev(seg, bus, dev_descr->dom, table); |
2296 | if (!sbridge_dev) { | 2303 | if (!sbridge_dev) { |
2297 | pci_dev_put(pdev); | 2304 | pci_dev_put(pdev); |
2298 | return -ENOMEM; | 2305 | 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, | |||
408 | size_t count, loff_t *ppos) | 408 | size_t count, loff_t *ppos) |
409 | { | 409 | { |
410 | struct thunderx_lmc *lmc = file->private_data; | 410 | struct thunderx_lmc *lmc = file->private_data; |
411 | |||
412 | unsigned int cline_size = cache_line_size(); | 411 | unsigned int cline_size = cache_line_size(); |
413 | 412 | u8 *tmp; | |
414 | u8 tmp[cline_size]; | ||
415 | void __iomem *addr; | 413 | void __iomem *addr; |
416 | unsigned int offs, timeout = 100000; | 414 | unsigned int offs, timeout = 100000; |
417 | 415 | ||
418 | atomic_set(&lmc->ecc_int, 0); | 416 | atomic_set(&lmc->ecc_int, 0); |
419 | 417 | ||
420 | lmc->mem = alloc_pages_node(lmc->node, GFP_KERNEL, 0); | 418 | lmc->mem = alloc_pages_node(lmc->node, GFP_KERNEL, 0); |
421 | |||
422 | if (!lmc->mem) | 419 | if (!lmc->mem) |
423 | return -ENOMEM; | 420 | return -ENOMEM; |
424 | 421 | ||
422 | tmp = kmalloc(cline_size, GFP_KERNEL); | ||
423 | if (!tmp) { | ||
424 | __free_pages(lmc->mem, 0); | ||
425 | return -ENOMEM; | ||
426 | } | ||
427 | |||
425 | addr = page_address(lmc->mem); | 428 | addr = page_address(lmc->mem); |
426 | 429 | ||
427 | while (!atomic_read(&lmc->ecc_int) && timeout--) { | 430 | while (!atomic_read(&lmc->ecc_int) && timeout--) { |
428 | stop_machine(inject_ecc_fn, lmc, NULL); | 431 | stop_machine(inject_ecc_fn, lmc, NULL); |
429 | 432 | ||
430 | for (offs = 0; offs < PAGE_SIZE; offs += sizeof(tmp)) { | 433 | for (offs = 0; offs < PAGE_SIZE; offs += cline_size) { |
431 | /* | 434 | /* |
432 | * Do a load from the previously rigged location | 435 | * Do a load from the previously rigged location |
433 | * This should generate an error interrupt. | 436 | * This should generate an error interrupt. |
@@ -437,6 +440,7 @@ static ssize_t thunderx_lmc_inject_ecc_write(struct file *file, | |||
437 | } | 440 | } |
438 | } | 441 | } |
439 | 442 | ||
443 | kfree(tmp); | ||
440 | __free_pages(lmc->mem, 0); | 444 | __free_pages(lmc->mem, 0); |
441 | 445 | ||
442 | return count; | 446 | return count; |