Skip to content

Commit e09060b

Browse files
ij-intelbjorn-helgaas
authored andcommitted
PCI/ASPM: Use RMW accessors for changing LNKCTL
Don't assume that the device is fully under the control of ASPM and use RMW capability accessors which do proper locking to avoid losing concurrent updates to the register values. If configuration fails in pcie_aspm_configure_common_clock(), the function attempts to restore the old PCI_EXP_LNKCTL_CCC settings. Store only the old PCI_EXP_LNKCTL_CCC bit for the relevant devices rather than the content of the whole LNKCTL registers. It aligns better with how pcie_lnkctl_clear_and_set() expects its parameter and makes the code more obvious to understand. Suggested-by: Lukas Wunner <lukas@wunner.de> Fixes: 2a42d9d ("PCIe: ASPM: Break out of endless loop waiting for PCI config bits to switch") Fixes: 7d715a6 ("PCI: add PCI Express ASPM support") Link: https://lore.kernel.org/r/20230717120503.15276-5-ilpo.jarvinen@linux.intel.com Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: "Rafael J. Wysocki" <rafael@kernel.org>
1 parent 5f75f96 commit e09060b

1 file changed

Lines changed: 13 additions & 17 deletions

File tree

drivers/pci/pcie/aspm.c

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
199199
static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
200200
{
201201
int same_clock = 1;
202-
u16 reg16, parent_reg, child_reg[8];
202+
u16 reg16, ccc, parent_old_ccc, child_old_ccc[8];
203203
struct pci_dev *child, *parent = link->pdev;
204204
struct pci_bus *linkbus = parent->subordinate;
205205
/*
@@ -221,6 +221,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
221221

222222
/* Port might be already in common clock mode */
223223
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
224+
parent_old_ccc = reg16 & PCI_EXP_LNKCTL_CCC;
224225
if (same_clock && (reg16 & PCI_EXP_LNKCTL_CCC)) {
225226
bool consistent = true;
226227

@@ -237,34 +238,29 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
237238
pci_info(parent, "ASPM: current common clock configuration is inconsistent, reconfiguring\n");
238239
}
239240

241+
ccc = same_clock ? PCI_EXP_LNKCTL_CCC : 0;
240242
/* Configure downstream component, all functions */
241243
list_for_each_entry(child, &linkbus->devices, bus_list) {
242244
pcie_capability_read_word(child, PCI_EXP_LNKCTL, &reg16);
243-
child_reg[PCI_FUNC(child->devfn)] = reg16;
244-
if (same_clock)
245-
reg16 |= PCI_EXP_LNKCTL_CCC;
246-
else
247-
reg16 &= ~PCI_EXP_LNKCTL_CCC;
248-
pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16);
245+
child_old_ccc[PCI_FUNC(child->devfn)] = reg16 & PCI_EXP_LNKCTL_CCC;
246+
pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
247+
PCI_EXP_LNKCTL_CCC, ccc);
249248
}
250249

251250
/* Configure upstream component */
252-
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &reg16);
253-
parent_reg = reg16;
254-
if (same_clock)
255-
reg16 |= PCI_EXP_LNKCTL_CCC;
256-
else
257-
reg16 &= ~PCI_EXP_LNKCTL_CCC;
258-
pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
251+
pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
252+
PCI_EXP_LNKCTL_CCC, ccc);
259253

260254
if (pcie_retrain_link(link->pdev, true)) {
261255

262256
/* Training failed. Restore common clock configurations */
263257
pci_err(parent, "ASPM: Could not configure common clock\n");
264258
list_for_each_entry(child, &linkbus->devices, bus_list)
265-
pcie_capability_write_word(child, PCI_EXP_LNKCTL,
266-
child_reg[PCI_FUNC(child->devfn)]);
267-
pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg);
259+
pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
260+
PCI_EXP_LNKCTL_CCC,
261+
child_old_ccc[PCI_FUNC(child->devfn)]);
262+
pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
263+
PCI_EXP_LNKCTL_CCC, parent_old_ccc);
268264
}
269265
}
270266

0 commit comments

Comments
 (0)