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

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
...@@ -637,10 +637,19 @@ static inline int numcol(u32 mtr) ...@@ -637,10 +637,19 @@ static inline int numcol(u32 mtr)
return 1 << cols; 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; 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) { list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
if (sbridge_dev->bus == bus) if (sbridge_dev->bus == bus)
return sbridge_dev; return sbridge_dev;
...@@ -1588,7 +1597,8 @@ static void sbridge_put_all_devices(void) ...@@ -1588,7 +1597,8 @@ static void sbridge_put_all_devices(void)
static int sbridge_get_onedevice(struct pci_dev **prev, static int sbridge_get_onedevice(struct pci_dev **prev,
u8 *num_mc, u8 *num_mc,
const struct pci_id_table *table, const struct pci_id_table *table,
const unsigned devno) const unsigned devno,
const int multi_bus)
{ {
struct sbridge_dev *sbridge_dev; struct sbridge_dev *sbridge_dev;
const struct pci_id_descr *dev_descr = &table->descr[devno]; const struct pci_id_descr *dev_descr = &table->descr[devno];
...@@ -1624,7 +1634,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -1624,7 +1634,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
} }
bus = pdev->bus->number; bus = pdev->bus->number;
sbridge_dev = get_sbridge_dev(bus); sbridge_dev = get_sbridge_dev(bus, multi_bus);
if (!sbridge_dev) { if (!sbridge_dev) {
sbridge_dev = alloc_sbridge_dev(bus, table); sbridge_dev = alloc_sbridge_dev(bus, table);
if (!sbridge_dev) { if (!sbridge_dev) {
...@@ -1673,21 +1683,32 @@ static int sbridge_get_onedevice(struct pci_dev **prev, ...@@ -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 * @num_mc: pointer to the memory controllers count, to be incremented in case
* of success. * of success.
* @table: model specific table * @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 * returns 0 in case of success or error code
*/ */
static int sbridge_get_all_devices(u8 *num_mc, static int sbridge_get_all_devices_full(u8 *num_mc,
const struct pci_id_table *table) const struct pci_id_table *table,
int allow_dups,
int multi_bus)
{ {
int i, rc; int i, rc;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
while (table && table->descr) { while (table && table->descr) {
for (i = 0; i < table->n_devs; i++) { for (i = 0; i < table->n_devs; i++) {
pdev = NULL; if (!allow_dups || i == 0 ||
table->descr[i].dev_id !=
table->descr[i-1].dev_id) {
pdev = NULL;
}
do { do {
rc = sbridge_get_onedevice(&pdev, num_mc, rc = sbridge_get_onedevice(&pdev, num_mc,
table, i); table, i, multi_bus);
if (rc < 0) { if (rc < 0) {
if (i == 0) { if (i == 0) {
i = table->n_devs; i = table->n_devs;
...@@ -1696,7 +1717,7 @@ static int sbridge_get_all_devices(u8 *num_mc, ...@@ -1696,7 +1717,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
sbridge_put_all_devices(); sbridge_put_all_devices();
return -ENODEV; return -ENODEV;
} }
} while (pdev); } while (pdev && !allow_dups);
} }
table++; table++;
} }
...@@ -1704,6 +1725,9 @@ static int sbridge_get_all_devices(u8 *num_mc, ...@@ -1704,6 +1725,9 @@ static int sbridge_get_all_devices(u8 *num_mc,
return 0; 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, static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev) struct sbridge_dev *sbridge_dev)
{ {
......
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