diff options
Diffstat (limited to 'drivers/misc/cxl/pci.c')
-rw-r--r-- | drivers/misc/cxl/pci.c | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 02c85160bfe9..85761d7eb333 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
@@ -1035,6 +1035,32 @@ static int cxl_read_vsec(struct cxl *adapter, struct pci_dev *dev) | |||
1035 | return 0; | 1035 | return 0; |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | /* | ||
1039 | * Workaround a PCIe Host Bridge defect on some cards, that can cause | ||
1040 | * malformed Transaction Layer Packet (TLP) errors to be erroneously | ||
1041 | * reported. Mask this error in the Uncorrectable Error Mask Register. | ||
1042 | * | ||
1043 | * The upper nibble of the PSL revision is used to distinguish between | ||
1044 | * different cards. The affected ones have it set to 0. | ||
1045 | */ | ||
1046 | static void cxl_fixup_malformed_tlp(struct cxl *adapter, struct pci_dev *dev) | ||
1047 | { | ||
1048 | int aer; | ||
1049 | u32 data; | ||
1050 | |||
1051 | if (adapter->psl_rev & 0xf000) | ||
1052 | return; | ||
1053 | if (!(aer = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))) | ||
1054 | return; | ||
1055 | pci_read_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, &data); | ||
1056 | if (data & PCI_ERR_UNC_MALF_TLP) | ||
1057 | if (data & PCI_ERR_UNC_INTN) | ||
1058 | return; | ||
1059 | data |= PCI_ERR_UNC_MALF_TLP; | ||
1060 | data |= PCI_ERR_UNC_INTN; | ||
1061 | pci_write_config_dword(dev, aer + PCI_ERR_UNCOR_MASK, data); | ||
1062 | } | ||
1063 | |||
1038 | static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev) | 1064 | static int cxl_vsec_looks_ok(struct cxl *adapter, struct pci_dev *dev) |
1039 | { | 1065 | { |
1040 | if (adapter->vsec_status & CXL_STATUS_SECOND_PORT) | 1066 | if (adapter->vsec_status & CXL_STATUS_SECOND_PORT) |
@@ -1134,6 +1160,8 @@ static int cxl_configure_adapter(struct cxl *adapter, struct pci_dev *dev) | |||
1134 | if ((rc = cxl_vsec_looks_ok(adapter, dev))) | 1160 | if ((rc = cxl_vsec_looks_ok(adapter, dev))) |
1135 | return rc; | 1161 | return rc; |
1136 | 1162 | ||
1163 | cxl_fixup_malformed_tlp(adapter, dev); | ||
1164 | |||
1137 | if ((rc = setup_cxl_bars(dev))) | 1165 | if ((rc = setup_cxl_bars(dev))) |
1138 | return rc; | 1166 | return rc; |
1139 | 1167 | ||
@@ -1249,8 +1277,6 @@ static int cxl_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1249 | int slice; | 1277 | int slice; |
1250 | int rc; | 1278 | int rc; |
1251 | 1279 | ||
1252 | pci_dev_get(dev); | ||
1253 | |||
1254 | if (cxl_verbose) | 1280 | if (cxl_verbose) |
1255 | dump_cxl_config_space(dev); | 1281 | dump_cxl_config_space(dev); |
1256 | 1282 | ||