summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQiuxu Zhuo <qiuxu.zhuo@intel.com>2017-08-14 23:48:45 +0800
committerBorislav Petkov <bp@suse.de>2017-08-19 10:47:24 +0200
commit5fd77cb3bac77f690d1d9cf57dc7851fcb3e7945 (patch)
tree269ceff2bff83778940cf2f4750798530b624688
parentd84676a9e12817c8435e836911800bdcc67928a0 (diff)
downloadlinux-5fd77cb3bac77f690d1d9cf57dc7851fcb3e7945.tar.bz2
EDAC, pnd2: Conditionally unhide/hide the P2SB PCI device to read BAR
On Deverton server, the P2SB PCI device (DEV:1F, FUN:1) is used by multiple device drivers. If it's hidden by some device driver (e.g. with the i801 I2C driver, the commit 9424693035a5 ("i2c: i801: Create iTCO device on newer Intel PCHs") unconditionally hid the P2SB PCI device wrongly) it will make the pnd2_edac driver read out an invalid BAR value of 0xffffffff and then fail on ioremap(). Therefore, store the presence state of P2SB PCI device before unhiding it for reading BAR and restore the presence state after reading BAR. Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Cc: Tony Luck <tony.luck@intel.com> Cc: linux-edac <linux-edac@vger.kernel.org> Cc: linux-i2c@vger.kernel.org Link: http://lkml.kernel.org/r/20170814154845.21663-1-qiuxu.zhuo@intel.com Signed-off-by: Borislav Petkov <bp@suse.de>
-rw-r--r--drivers/edac/pnd2_edac.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c
index 2b16b95201eb..89cdd9a7a733 100644
--- a/drivers/edac/pnd2_edac.c
+++ b/drivers/edac/pnd2_edac.c
@@ -236,12 +236,23 @@ static u64 get_sideband_reg_base_addr(void)
{
struct pci_dev *pdev;
u32 hi, lo;
+ u8 hidden;
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x19dd, NULL);
if (pdev) {
+ /* Unhide the P2SB device, if it's hidden */
+ pci_read_config_byte(pdev, 0xe1, &hidden);
+ if (hidden)
+ pci_write_config_byte(pdev, 0xe1, 0);
+
pci_read_config_dword(pdev, 0x10, &lo);
pci_read_config_dword(pdev, 0x14, &hi);
lo &= 0xfffffff0;
+
+ /* Hide the P2SB device, if it was hidden before */
+ if (hidden)
+ pci_write_config_byte(pdev, 0xe1, hidden);
+
pci_dev_put(pdev);
return (U64_LSHIFT(hi, 32) | U64_LSHIFT(lo, 0));
} else {