summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorRajat Jain <rajatja@google.com>2021-12-22 04:21:05 +0300
committerBjorn Helgaas <bhelgaas@google.com>2022-01-11 19:41:24 +0300
commit4353594eb0980c80e24ebb20d9c871ff95b3b789 (patch)
tree797564c741987b5af3ea2956bb557c4c874e5b85 /drivers/pci/pci.c
parent0cf948aab9a0049456d9a498af3da6b403e2a0ed (diff)
downloadlinux-4353594eb0980c80e24ebb20d9c871ff95b3b789.tar.xz
PCI: Use DWORD accesses for LTR, L1 SS to avoid erratum
Some devices have an erratum such that they only support DWORD accesses to some registers. E.g., this Bayhub O2 device ([VID:DID] = [0x1217:0x8621]) only supports DWORD accesses to LTR latency registers and L1 PM substates control registers: https://github.com/rajatxjain/public_shared/blob/main/OZ711LV2_appnote.pdf The L1 PM substate control registers are DWORD sized, and hence their access in the kernel is already DWORD sized, so we don't need to do anything for them. However, the LTR registers being WORD sized, are in need of a solution. Convert the WORD sized accesses to these registers into DWORD sized accesses while saving and restoring them. Link: https://lore.kernel.org/r/20211222012105.3438916-1-rajatja@google.com Signed-off-by: Rajat Jain <rajatja@google.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3d2fb394986a..287fa40f763c 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1556,7 +1556,7 @@ static void pci_save_ltr_state(struct pci_dev *dev)
{
int ltr;
struct pci_cap_saved_state *save_state;
- u16 *cap;
+ u32 *cap;
if (!pci_is_pcie(dev))
return;
@@ -1571,25 +1571,25 @@ static void pci_save_ltr_state(struct pci_dev *dev)
return;
}
- cap = (u16 *)&save_state->cap.data[0];
- pci_read_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap++);
- pci_read_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, cap++);
+ /* Some broken devices only support dword access to LTR */
+ cap = &save_state->cap.data[0];
+ pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap);
}
static void pci_restore_ltr_state(struct pci_dev *dev)
{
struct pci_cap_saved_state *save_state;
int ltr;
- u16 *cap;
+ u32 *cap;
save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
if (!save_state || !ltr)
return;
- cap = (u16 *)&save_state->cap.data[0];
- pci_write_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap++);
- pci_write_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, *cap++);
+ /* Some broken devices only support dword access to LTR */
+ cap = &save_state->cap.data[0];
+ pci_write_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap);
}
/**