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

Commit dbc954dd authored by Aristeu Rozanski's avatar Aristeu Rozanski Committed by Mauro Carvalho Chehab
Browse files

sb_edac: search devices using product id



This patch changes the way devices are searched by using product id instead of
device/function numbers. Tested in a Sandy Bridge and a Ivy Bridge machine to
make sure everything works properly.

Cc: Tony Luck <tony.luck@intel.com>
Signed-off-by: default avatarAristeu Rozanski <aris@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <m.chehab@samsung.com>
parent b976bcf2
Loading
Loading
Loading
Loading
+137 −215
Original line number Diff line number Diff line
@@ -311,8 +311,6 @@ struct sbridge_channel {
};

struct pci_id_descr {
	int			dev;
	int			func;
	int 			dev_id;
	int			optional;
};
@@ -360,31 +358,29 @@ struct sbridge_pvt {
	u64			tolm, tohm;
};

#define PCI_DESCR(device, function, device_id, opt)	\
	.dev = (device),				\
	.func = (function),				\
#define PCI_DESCR(device_id, opt)	\
	.dev_id = (device_id),		\
	.optional = opt

static const struct pci_id_descr pci_dev_descr_sbridge[] = {
		/* Processor Home Agent */
	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0, 0)	},

		/* Memory controller */
	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)	},
	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)	},
	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)	},
	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)	},
	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)	},
	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)	},
	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO, 1)	},

		/* System Address Decoder */
	{ PCI_DESCR(12, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)		},
	{ PCI_DESCR(12, 7, PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1, 0)	},

		/* Broadcast Registers */
	{ PCI_DESCR(13, 6, PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_SBRIDGE_BR, 0)		},
};

#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
@@ -421,34 +417,34 @@ static const struct pci_id_table pci_dev_descr_sbridge_table[] = {

static const struct pci_id_descr pci_dev_descr_ibridge[] = {
		/* Processor Home Agent */
	{ PCI_DESCR(14, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0, 0)		},

		/* Memory controller */
	{ PCI_DESCR(15, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)	},
	{ PCI_DESCR(15, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)	},
	{ PCI_DESCR(15, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0)	},
	{ PCI_DESCR(15, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0)	},
	{ PCI_DESCR(15, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0)	},
	{ PCI_DESCR(15, 5, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2, 0)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3, 0)	},

		/* System Address Decoder */
	{ PCI_DESCR(22, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_SAD, 0)			},

		/* Broadcast Registers */
	{ PCI_DESCR(22, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)		},
	{ PCI_DESCR(22, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)		},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR0, 1)			},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_BR1, 0)			},

		/* Optional, mode 2HA */
	{ PCI_DESCR(28, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1, 1)		},
#if 0
	{ PCI_DESCR(29, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)	},
	{ PCI_DESCR(29, 1, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TA, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_RAS, 1)	},
#endif
	{ PCI_DESCR(29, 2, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1)	},
	{ PCI_DESCR(29, 3, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1, 1)	},

	{ PCI_DESCR(17, 0, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1) },
	{ PCI_DESCR(17, 4, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1) },
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0, 1)	},
	{ PCI_DESCR(PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0, 1)	},
};

static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
@@ -631,44 +627,38 @@ static inline u8 sad_pkg_ha(u8 pkg)
/****************************************************************************
			Memory check routines
 ****************************************************************************/
static struct pci_dev *get_pdev_slot_func(u8 bus, unsigned slot,
					  unsigned func)
static struct pci_dev *get_pdev_same_bus(u8 bus, u32 id)
{
	struct sbridge_dev *sbridge_dev = get_sbridge_dev(bus);
	int i;

	if (!sbridge_dev)
		return NULL;

	for (i = 0; i < sbridge_dev->n_devs; i++) {
		if (!sbridge_dev->pdev[i])
			continue;
	struct pci_dev *pdev = NULL;

		if (PCI_SLOT(sbridge_dev->pdev[i]->devfn) == slot &&
		    PCI_FUNC(sbridge_dev->pdev[i]->devfn) == func) {
			edac_dbg(1, "Associated %02x.%02x.%d with %p\n",
				 bus, slot, func, sbridge_dev->pdev[i]);
			return sbridge_dev->pdev[i];
		}
	}
	do {
		pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, pdev);
		if (pdev && pdev->bus->number == bus)
			break;
	} while (pdev);

	return NULL;
	return pdev;
}

/**
 * check_if_ecc_is_active() - Checks if ECC is active
 * bus:		Device bus
 */
static int check_if_ecc_is_active(const u8 bus)
static int check_if_ecc_is_active(const u8 bus, enum type type)
{
	struct pci_dev *pdev = NULL;
	u32 mcmtr;
	u32 mcmtr, id;

	if (type == IVY_BRIDGE)
		id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
	else
		id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;

	pdev = get_pdev_slot_func(bus, 15, 0);
	pdev = get_pdev_same_bus(bus, id);
	if (!pdev) {
		sbridge_printk(KERN_ERR, "Couldn't find PCI device "
					"%2x.%02d.%d!!!\n",
					bus, 15, 0);
					"%04x:%04x! on bus %02d\n",
					PCI_VENDOR_ID_INTEL, id, bus);
		return -ENODEV;
	}

@@ -1279,13 +1269,11 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
{
	struct sbridge_dev *sbridge_dev;
	const struct pci_id_descr *dev_descr = &table->descr[devno];

	struct pci_dev *pdev = NULL;
	u8 bus = 0;

	sbridge_printk(KERN_DEBUG,
		"Seeking for: dev %02x.%d PCI ID %04x:%04x\n",
		dev_descr->dev, dev_descr->func,
		"Seeking for: PCI ID %04x:%04x\n",
		PCI_VENDOR_ID_INTEL, dev_descr->dev_id);

	pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1300,12 +1288,12 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
		if (dev_descr->optional)
			return 0;

		/* if the HA wasn't found */
		if (devno == 0)
			return -ENODEV;

		sbridge_printk(KERN_INFO,
			"Device not found: dev %02x.%d PCI ID %04x:%04x\n",
			dev_descr->dev, dev_descr->func,
			"Device not found: %04x:%04x\n",
			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);

		/* End of list, leave */
@@ -1325,9 +1313,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,

	if (sbridge_dev->pdev[devno]) {
		sbridge_printk(KERN_ERR,
			"Duplicated device for "
			"dev %02x:%d.%d PCI ID %04x:%04x\n",
			bus, dev_descr->dev, dev_descr->func,
			"Duplicated device for %04x:%04x\n",
			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
		pci_dev_put(pdev);
		return -ENODEV;
@@ -1335,30 +1321,15 @@ static int sbridge_get_onedevice(struct pci_dev **prev,

	sbridge_dev->pdev[devno] = pdev;

	/* Sanity check */
	if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
			PCI_FUNC(pdev->devfn) != dev_descr->func)) {
		sbridge_printk(KERN_ERR,
			"Device PCI ID %04x:%04x "
			"has dev %02x:%d.%d instead of dev %02x:%02x.%d\n",
			PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
			bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
			bus, dev_descr->dev, dev_descr->func);
		return -ENODEV;
	}

	/* Be sure that the device is enabled */
	if (unlikely(pci_enable_device(pdev) < 0)) {
		sbridge_printk(KERN_ERR,
			"Couldn't enable "
			"dev %02x:%d.%d PCI ID %04x:%04x\n",
			bus, dev_descr->dev, dev_descr->func,
			"Couldn't enable %04x:%04x\n",
			PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
		return -ENODEV;
	}

	edac_dbg(0, "Detected dev %02x:%d.%d PCI ID %04x:%04x\n",
		 bus, dev_descr->dev, dev_descr->func,
	edac_dbg(0, "Detected %04x:%04x\n",
		 PCI_VENDOR_ID_INTEL, dev_descr->dev_id);

	/*
@@ -1375,8 +1346,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,

/*
 * sbridge_get_all_devices - Find and perform 'get' operation on the MCH's
 *			     device/functions we want to reference for this driver.
 *			     Need to 'get' device 16 func 1 and func 2.
 *			     devices we want to reference for this driver.
 * @num_mc: pointer to the memory controllers count, to be incremented in case
 * 	    of success.
 * @table: model specific table
@@ -1416,79 +1386,51 @@ static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
{
	struct sbridge_pvt *pvt = mci->pvt_info;
	struct pci_dev *pdev;
	int i, func, slot;
	int i;

	for (i = 0; i < sbridge_dev->n_devs; i++) {
		pdev = sbridge_dev->pdev[i];
		if (!pdev)
			continue;
		slot = PCI_SLOT(pdev->devfn);
		func = PCI_FUNC(pdev->devfn);
		switch (slot) {
		case 12:
			switch (func) {
			case 6:

		switch (pdev->device) {
		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD0:
			pvt->pci_sad0 = pdev;
			break;
			case 7:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_SAD1:
			pvt->pci_sad1 = pdev;
			break;
			default:
				goto error;
			}
			break;
		case 13:
			switch (func) {
			case 6:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_BR:
			pvt->pci_br0 = pdev;
			break;
			default:
				goto error;
			}
			break;
		case 14:
			switch (func) {
			case 0:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
			pvt->pci_ha0 = pdev;
			break;
			default:
				goto error;
			}
			break;
		case 15:
			switch (func) {
			case 0:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA:
			pvt->pci_ta = pdev;
			break;
			case 1:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_RAS:
			pvt->pci_ras = pdev;
			break;
			case 2:
			case 3:
			case 4:
			case 5:
				pvt->pci_tad[func - 2] = pdev;
				break;
			default:
				goto error;
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD1:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD2:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD3:
		{
			int id = pdev->device - PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TAD0;
			pvt->pci_tad[id] = pdev;
		}
			break;
		case 17:
			switch (func) {
			case 0:
		case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_DDRIO:
			pvt->pci_ddrio = pdev;
			break;
		default:
			goto error;
		}
			break;
		default:
			goto error;
		}

		edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
		edac_dbg(0, "Associated PCI %02x:%02x, bus %d with dev = %p\n",
			 pdev->vendor, pdev->device,
			 sbridge_dev->bus,
			 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
			 pdev);
	}

@@ -1508,9 +1450,8 @@ enodev:
	return -ENODEV;

error:
	sbridge_printk(KERN_ERR, "Device %d, function %d "
		      "is out of the expected range\n",
		      slot, func);
	sbridge_printk(KERN_ERR, "Unexpected device %02x:%02x\n",
		       PCI_VENDOR_ID_INTEL, pdev->device);
	return -EINVAL;
}

@@ -1519,7 +1460,7 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
{
	struct sbridge_pvt *pvt = mci->pvt_info;
	struct pci_dev *pdev, *tmp;
	int i, func, slot;
	int i;
	bool mode_2ha = false;

	tmp = pci_get_device(PCI_VENDOR_ID_INTEL,
@@ -1533,79 +1474,60 @@ static int ibridge_mci_bind_devs(struct mem_ctl_info *mci,
		pdev = sbridge_dev->pdev[i];
		if (!pdev)
			continue;
		slot = PCI_SLOT(pdev->devfn);
		func = PCI_FUNC(pdev->devfn);

		switch (slot) {
		case 14:
			if (func == 0) {
		switch (pdev->device) {
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0:
			pvt->pci_ha0 = pdev;
			break;
			}
			goto error;
		case 15:
			switch (func) {
			case 0:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
			pvt->pci_ta = pdev;
				break;
			case 1:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_RAS:
			pvt->pci_ras = pdev;
			break;
			case 4:
			case 5:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD2:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD3:
			/* if we have 2 HAs active, channels 2 and 3
			 * are in other device */
			if (mode_2ha)
				break;
			/* fall through */
			case 2:
			case 3:
				pvt->pci_tad[func - 2] = pdev;
				break;
			default:
				goto error;
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD1:
		{
			int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TAD0;
			pvt->pci_tad[id] = pdev;
		}
			break;
		case 17:
			if (func == 4) {
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_2HA_DDRIO0:
			pvt->pci_ddrio = pdev;
			break;
			} else if (func == 0) {
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_1HA_DDRIO0:
			if (!mode_2ha)
				pvt->pci_ddrio = pdev;
			break;
			}
			goto error;
		case 22:
			switch (func) {
			case 0:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_SAD:
			pvt->pci_sad0 = pdev;
			break;
			case 1:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_BR0:
			pvt->pci_br0 = pdev;
			break;
			case 2:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_BR1:
			pvt->pci_br1 = pdev;
			break;
			default:
				goto error;
			}
			break;
		case 28:
			if (func == 0) {
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1:
			pvt->pci_ha1 = pdev;
			break;
			}
			goto error;
		case 29:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0:
		case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD1:
		{
			int id = pdev->device - PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA1_TAD0 + 2;

			/* we shouldn't have this device if we have just one
			 * HA present */
			WARN_ON(!mode_2ha);
			if (func == 2 || func == 3) {
				pvt->pci_tad[func] = pdev;
				break;
			pvt->pci_tad[id] = pdev;
		}
			goto error;
			break;
		default:
			goto error;
		}
@@ -1634,8 +1556,8 @@ enodev:

error:
	sbridge_printk(KERN_ERR,
		       "Device %d, function %d is out of the expected range\n",
		       slot, func);
		       "Unexpected device %02x:%02x\n", PCI_VENDOR_ID_INTEL,
			pdev->device);
	return -EINVAL;
}

@@ -1952,7 +1874,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
	int rc;

	/* Check the number of active and not disabled channels */
	rc = check_if_ecc_is_active(sbridge_dev->bus);
	rc = check_if_ecc_is_active(sbridge_dev->bus, type);
	if (unlikely(rc < 0))
		return rc;