On Fri, Jun 2, 2023 at 11:57 PM Limonciello, Mario
<mario.limonciello@xxxxxxx> wrote:
As I said in my response to Bjorn, s2idle is D0 from the ACPI
On 6/2/2023 3:21 PM, Bjorn Helgaas wrote:
[+cc Rafael, Len, linux-acpi]It's important for the symptoms of this issue though, this
Hi Mario,
On Thu, Jun 01, 2023 at 10:11:22PM -0500, Mario Limonciello wrote:
ASMedia PCIe GPIO controllers connected to AMD SOC fail functional tests"s2idle" is a Linux term; I'd prefer something that we can relate to
after returning from s2idle. This is because the BIOS checks whether the
OSPM has called the _REG method to determine whether it can interact with
the OperationRegion assigned to the device.
the ACPI spec.
problem doesn't trigger "just" by moving D-states.
It happens as a result of system suspend.
standpoint. It is not a system sleep and it has no special meaning in
ACPI.
The problem seems to be related to the low-power S0 idle _DSM calls to me.
I didn't think it should be limited to suspend/resumeSo the argument seems to be that under certain conditions the PCIMaybe a pointer to the specific function in the driver that has aThe issue isn't in anything Linux code "does"; it's in the "lack"
problem? Based on the patch, I assume the driver uses some control
method that looks at PCI config space?
of Linux code doing what it needs to IE using _REG.
config space becomes unavailable and so _REG(dev, 0) needs to be
called when this is about to happen and _REG(dev, 1) needs to be
called when the config space becomes available again. Fair enough,
but I'm not sure why this is limited to system suspend and resume.
Moreover, "PCI_Config operation regions on a PCI root bus containing a
_BBN object" are specifically mentioned as one of the cases when _REG
need not be evaluated at all. I guess the operation region in
question doesn't fall into that category?
Access.At least for this issue _REG is treated like a lock mechanism.Is this about being unable to access the opregion or racing with
In the spec it says specifically:
"When an operation region handler is unavailable, AML cannot access
data fields in that region".
That is it's to ensure that OSPM and AML don't both simultaneously
access the same region.
What happens is that AML normally wants to access this region during
suspend, but without the sequence of calling _REG it can't.
concurrent accesses on the OS side?
OK.
I don't think it can reasonably become mandatory without adding aSure.To fix this issue, call acpi_evaluate_reg() when saving and restoring thePlease include the spec citation: ACPI r6.5, sec 6.5.4. The URL has
state of PCI devices.
changed in the past and may change in the future, but the name/section
number will not.
_REG isn't mandatory for any of these uses, and I wanted to makeLink: https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/06_Device_Configuration/Device_Configuration.html#reg-regionYou never check the return value, so why return it?
Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>
---
drivers/pci/pci.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e38c2f6eebd4..071ecba548b0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1068,6 +1068,12 @@ static inline bool platform_pci_bridge_d3(struct pci_dev *dev)
return acpi_pci_bridge_d3(dev);
}
+static inline int platform_toggle_reg(struct pci_dev *dev, int c)
+{
+ return acpi_evaluate_reg(ACPI_HANDLE(&dev->dev),
+ ACPI_ADR_SPACE_PCI_CONFIG, c);
+}
sure that if it does end up being mandatory in a future use that
the return code wasn't thrown away. If you think it's better to
just throw it away now, I have no qualms making it a void instead.
specific _OSC bit for that.
Yeah. When I discussed it with BIOS guys they
So it looks like you want to use _REG for protecting PCI config spaceThe function actually doesn't *toggle*; it connects or disconnectsCan you suggest a better function name?
based on "c".
This looks like it only builds when CONFIG_ACPI=y?The prototype for acpi_evaluate_reg isn't guarded by CONFIG_ACPI
so I figured it worked both ways.
But looking again I don't see a dummy implementation version for
the lack of CONFIG_ACPI, so I'll double check it.
My knee jerk reaction when we found the root cause for this issue/**I would expect these to be in the PM code near the power state
* pci_update_current_state - Read power state of given device and cache it
* @dev: PCI device to handle.
@@ -1645,6 +1651,9 @@ static void pci_restore_ltr_state(struct pci_dev *dev)
int pci_save_state(struct pci_dev *dev)
{
int i;
+
+ platform_toggle_reg(dev, ACPI_REG_DISCONNECT);
transitions, not in the state save/restore code. These functions
*are* used during suspend/resume, but are used in other places as
well, where we probably don't want _REG executed.
Cc'd Rafael and PM folks, who can give much better feedback.
was to put the code right around the D-state transitions, but I
decided against this.
I put it in save/restore intentionally because
like I mentioned above it's treated like a locking mechanism between
OSPM and AML and it's not functionally tied to a D-state transition.
When the state is saved it's like Linux says
"I'm done using this region, go ahead and touch it firmware".
When it's restored it's like Linux says
"Don't use that region, I'm claiming it for now".
against concurrent accesses from AML and the OS.
No matter what the actual D-state is the OSPM isn'tThink about that other patch I wrote recently that controls D3And why should it be evaluated in that case?
availability [1]. If it was only run in the D-state transitions and
the root port stays in D0 but has a _REG method it would never get
called.