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

Commit c1979ba2 authored by Jim Snow's avatar Jim Snow Committed by Borislav Petkov
Browse files

EDAC, sb_edac: Add support for duplicate device IDs



Add options to sbridge_get_all_devices() to allow for duplicate device
IDs and devices that are scattered across mulitple PCI buses.

Signed-off-by: default avatarJim Snow <jim.m.snow@intel.com>
Acked-by: default avatarTony Luck <tony.luck@intel.com>
Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Cc: linux-edac <linux-edac@vger.kernel.org>
Cc: lukasz.anaczkowski@intel.com
Link: http://lkml.kernel.org/r/1449136134-23706-4-git-send-email-hubert.chrzaniuk@intel.com


[ Rebase to 4.4-rc3. ]
Signed-off-by: default avatarHubert Chrzaniuk <hubert.chrzaniuk@intel.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent c59f9c06
Loading
Loading
Loading
Loading
+32 −8
Original line number Diff line number Diff line
@@ -637,10 +637,19 @@ static inline int numcol(u32 mtr)
	return 1 << cols;
}

static struct sbridge_dev *get_sbridge_dev(u8 bus)
static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus)
{
	struct sbridge_dev *sbridge_dev;

	/*
	 * If we have devices scattered across several busses that pertain
	 * to the same memory controller, we'll lump them all together.
	 */
	if (multi_bus) {
		return list_first_entry_or_null(&sbridge_edac_list,
				struct sbridge_dev, list);
	}

	list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
		if (sbridge_dev->bus == bus)
			return sbridge_dev;
@@ -1588,7 +1597,8 @@ static void sbridge_put_all_devices(void)
static int sbridge_get_onedevice(struct pci_dev **prev,
				 u8 *num_mc,
				 const struct pci_id_table *table,
				 const unsigned devno)
				 const unsigned devno,
				 const int multi_bus)
{
	struct sbridge_dev *sbridge_dev;
	const struct pci_id_descr *dev_descr = &table->descr[devno];
@@ -1624,7 +1634,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
	}
	bus = pdev->bus->number;

	sbridge_dev = get_sbridge_dev(bus);
	sbridge_dev = get_sbridge_dev(bus, multi_bus);
	if (!sbridge_dev) {
		sbridge_dev = alloc_sbridge_dev(bus, table);
		if (!sbridge_dev) {
@@ -1673,21 +1683,32 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
 * @num_mc: pointer to the memory controllers count, to be incremented in case
 *	    of success.
 * @table: model specific table
 * @allow_dups: allow for multiple devices to exist with the same device id
 *              (as implemented, this isn't expected to work correctly in the
 *              multi-socket case).
 * @multi_bus: don't assume devices on different buses belong to different
 *             memory controllers.
 *
 * returns 0 in case of success or error code
 */
static int sbridge_get_all_devices(u8 *num_mc,
				   const struct pci_id_table *table)
static int sbridge_get_all_devices_full(u8 *num_mc,
					const struct pci_id_table *table,
					int allow_dups,
					int multi_bus)
{
	int i, rc;
	struct pci_dev *pdev = NULL;

	while (table && table->descr) {
		for (i = 0; i < table->n_devs; i++) {
			if (!allow_dups || i == 0 ||
					table->descr[i].dev_id !=
						table->descr[i-1].dev_id) {
				pdev = NULL;
			}
			do {
				rc = sbridge_get_onedevice(&pdev, num_mc,
							   table, i);
							   table, i, multi_bus);
				if (rc < 0) {
					if (i == 0) {
						i = table->n_devs;
@@ -1696,7 +1717,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
					sbridge_put_all_devices();
					return -ENODEV;
				}
			} while (pdev);
			} while (pdev && !allow_dups);
		}
		table++;
	}
@@ -1704,6 +1725,9 @@ static int sbridge_get_all_devices(u8 *num_mc,
	return 0;
}

#define sbridge_get_all_devices(num_mc, table) \
		sbridge_get_all_devices_full(num_mc, table, 0, 0)

static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
				 struct sbridge_dev *sbridge_dev)
{