Commit 709ed1bc authored by Jason Baron's avatar Jason Baron Committed by Tony Luck

EDAC/ie31200: Fallback if host bridge device is already initialized

The Intel uncore driver may claim some of the pci ids from ie31200 which
means that the ie31200 edac driver will not initialize them as part of
pci_register_driver().

Let's add a fallback for this case to 'pci_get_device()' to get a
reference on the device such that it can still be configured. This is
similar in approach to other edac drivers.
Signed-off-by: default avatarJason Baron <jbaron@akamai.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: linux-edac <linux-edac@vger.kernel.org>
Signed-off-by: default avatarTony Luck <tony.luck@intel.com>
Link: https://lore.kernel.org/r/1594923911-10885-1-git-send-email-jbaron@akamai.com
parent 0f959e19
...@@ -170,6 +170,8 @@ ...@@ -170,6 +170,8 @@
(n << (28 + (2 * skl) - PAGE_SHIFT)) (n << (28 + (2 * skl) - PAGE_SHIFT))
static int nr_channels; static int nr_channels;
static struct pci_dev *mci_pdev;
static int ie31200_registered = 1;
struct ie31200_priv { struct ie31200_priv {
void __iomem *window; void __iomem *window;
...@@ -538,12 +540,16 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) ...@@ -538,12 +540,16 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx)
static int ie31200_init_one(struct pci_dev *pdev, static int ie31200_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
edac_dbg(0, "MC:\n"); int rc;
edac_dbg(0, "MC:\n");
if (pci_enable_device(pdev) < 0) if (pci_enable_device(pdev) < 0)
return -EIO; return -EIO;
rc = ie31200_probe1(pdev, ent->driver_data);
if (rc == 0 && !mci_pdev)
mci_pdev = pci_dev_get(pdev);
return ie31200_probe1(pdev, ent->driver_data); return rc;
} }
static void ie31200_remove_one(struct pci_dev *pdev) static void ie31200_remove_one(struct pci_dev *pdev)
...@@ -552,6 +558,8 @@ static void ie31200_remove_one(struct pci_dev *pdev) ...@@ -552,6 +558,8 @@ static void ie31200_remove_one(struct pci_dev *pdev)
struct ie31200_priv *priv; struct ie31200_priv *priv;
edac_dbg(0, "\n"); edac_dbg(0, "\n");
pci_dev_put(mci_pdev);
mci_pdev = NULL;
mci = edac_mc_del_mc(&pdev->dev); mci = edac_mc_del_mc(&pdev->dev);
if (!mci) if (!mci)
return; return;
...@@ -593,17 +601,53 @@ static struct pci_driver ie31200_driver = { ...@@ -593,17 +601,53 @@ static struct pci_driver ie31200_driver = {
static int __init ie31200_init(void) static int __init ie31200_init(void)
{ {
int pci_rc, i;
edac_dbg(3, "MC:\n"); edac_dbg(3, "MC:\n");
/* Ensure that the OPSTATE is set correctly for POLL or NMI */ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init(); opstate_init();
return pci_register_driver(&ie31200_driver); pci_rc = pci_register_driver(&ie31200_driver);
if (pci_rc < 0)
goto fail0;
if (!mci_pdev) {
ie31200_registered = 0;
for (i = 0; ie31200_pci_tbl[i].vendor != 0; i++) {
mci_pdev = pci_get_device(ie31200_pci_tbl[i].vendor,
ie31200_pci_tbl[i].device,
NULL);
if (mci_pdev)
break;
}
if (!mci_pdev) {
edac_dbg(0, "ie31200 pci_get_device fail\n");
pci_rc = -ENODEV;
goto fail1;
}
pci_rc = ie31200_init_one(mci_pdev, &ie31200_pci_tbl[i]);
if (pci_rc < 0) {
edac_dbg(0, "ie31200 init fail\n");
pci_rc = -ENODEV;
goto fail1;
}
}
return 0;
fail1:
pci_unregister_driver(&ie31200_driver);
fail0:
pci_dev_put(mci_pdev);
return pci_rc;
} }
static void __exit ie31200_exit(void) static void __exit ie31200_exit(void)
{ {
edac_dbg(3, "MC:\n"); edac_dbg(3, "MC:\n");
pci_unregister_driver(&ie31200_driver); pci_unregister_driver(&ie31200_driver);
if (!ie31200_registered)
ie31200_remove_one(mci_pdev);
} }
module_init(ie31200_init); module_init(ie31200_init);
......
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