Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c1c2ad82 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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,
+3 −3
Original line number Diff line number Diff line
@@ -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;
}
+15 −7
Original line number Diff line number Diff line
@@ -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);
}

/****************************************************************************
+12 −5
Original line number Diff line number Diff line
@@ -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 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
		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;
+9 −5
Original line number Diff line number Diff line
@@ -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;