Skip to content

Commit 4353594

Browse files
Rajat Jainbjorn-helgaas
authored andcommitted
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>
1 parent 0cf948a commit 4353594

2 files changed

Lines changed: 9 additions & 8 deletions

File tree

drivers/pci/pci.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ static void pci_save_ltr_state(struct pci_dev *dev)
15561556
{
15571557
int ltr;
15581558
struct pci_cap_saved_state *save_state;
1559-
u16 *cap;
1559+
u32 *cap;
15601560

15611561
if (!pci_is_pcie(dev))
15621562
return;
@@ -1571,25 +1571,25 @@ static void pci_save_ltr_state(struct pci_dev *dev)
15711571
return;
15721572
}
15731573

1574-
cap = (u16 *)&save_state->cap.data[0];
1575-
pci_read_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap++);
1576-
pci_read_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, cap++);
1574+
/* Some broken devices only support dword access to LTR */
1575+
cap = &save_state->cap.data[0];
1576+
pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap);
15771577
}
15781578

15791579
static void pci_restore_ltr_state(struct pci_dev *dev)
15801580
{
15811581
struct pci_cap_saved_state *save_state;
15821582
int ltr;
1583-
u16 *cap;
1583+
u32 *cap;
15841584

15851585
save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
15861586
ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
15871587
if (!save_state || !ltr)
15881588
return;
15891589

1590-
cap = (u16 *)&save_state->cap.data[0];
1591-
pci_write_config_word(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap++);
1592-
pci_write_config_word(dev, ltr + PCI_LTR_MAX_NOSNOOP_LAT, *cap++);
1590+
/* Some broken devices only support dword access to LTR */
1591+
cap = &save_state->cap.data[0];
1592+
pci_write_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap);
15931593
}
15941594

15951595
/**

drivers/pci/pcie/aspm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ static void aspm_calc_l1ss_info(struct pcie_link_state *link,
496496
encode_l12_threshold(l1_2_threshold, &scale, &value);
497497
ctl1 |= t_common_mode << 8 | scale << 29 | value << 16;
498498

499+
/* Some broken devices only support dword access to L1 SS */
499500
pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, &pctl1);
500501
pci_read_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, &pctl2);
501502
pci_read_config_dword(child, child->l1ss + PCI_L1SS_CTL1, &cctl1);

0 commit comments

Comments
 (0)