Message ID | 20240202071110.8515-3-jhp@endlessos.org |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-49365-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp261980dyc; Thu, 1 Feb 2024 23:25:42 -0800 (PST) X-Google-Smtp-Source: AGHT+IHP6eOxypi/q3mmPz4GEnjfjVyKpgbZyPf3oPRLL599xMNupDOkO5COne/X3b5JgQ7x6Q2q X-Received: by 2002:a17:906:7b82:b0:a35:e197:c94f with SMTP id s2-20020a1709067b8200b00a35e197c94fmr927197ejo.69.1706858741794; Thu, 01 Feb 2024 23:25:41 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706858741; cv=pass; d=google.com; s=arc-20160816; b=hvChIVxJEa6RgOC6QWZRFCu8B9ny0LVYSpXaAj86g/7w6iHF1SRLE8gQsxPb26JH6o zwJlywUDbdh+kEf5wSZPmibXHgjnZ5DNQ5QPYLp8DF8E1z78MJZLnRiLx7c3fvgybf7t Z30rs2n0yRyx57CMiXS0KT/B8841/TOFx8cPfpD+xmmO+ljvc5og86jc76R8CCnHZiLZ sorlHpG7sgQC6epBYoHw6TT3f/lgPeklpYAdyZiLiljclVCubY5Adi5MKk7s6SV9Tw/5 lSbASOfqviLia2pY1s2zwMhnPRdltYCmMq9CJhSfX+kDpM61PRydpmiZDWARiUOF74S6 SNRQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from:dkim-signature; bh=NZkIYyyqlYFNT1lqciy923TmN3UIp12qeGkpjnu4yVM=; fh=amJRzg5AkZyubFQaSK3wIhHo+bsJuNLMzSDCsNxCOxo=; b=IU2OX3GOW9xaE9R4bKK48mIWu0mQTdD9kjXb2okiLb/i97linNoaEGDZO9EpnrPlCw oO0nco6gOYUvCCSMtEv2+cugEQkwz8RXxytKOPm4b8ebG9q+7xvOqdsDrLjzmtpvn6XV Sv0KRtDHDeHFlk047mn5Pk9zXU1W6vLW/KT1ndtsjz+VDASe2QDun0+SioNTCa5QJc4l J/b5gWC0BkYfLMVyNb56wCiLF2gi3jnpE0jDCMq3+Hkt0+9jZG0G4zekOP+6Ug9+8nld j/PQ/x0BF1UOsDo8lnulREUyfRQMTDDLw8jm/JpHZwZ0w9T00n4DBgIWKDRCclZ7IZ2M vpuw==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@endlessos.org header.s=google header.b=c7TQfoqV; arc=pass (i=1 spf=pass spfdomain=endlessos.org dkim=pass dkdomain=endlessos.org dmarc=pass fromdomain=endlessos.org); spf=pass (google.com: domain of linux-kernel+bounces-49365-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49365-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=endlessos.org X-Forwarded-Encrypted: i=1; AJvYcCXTqPdQDgqQ3+heUF5Eveep4Rlx+cgWnKPmNfsGymARcr+5bB2N62AeRrMiPhN0bqDK4SXuUZy5+68MXyWSVgsOi30ZEg== Received: from am.mirrors.kernel.org (am.mirrors.kernel.org. [147.75.80.249]) by mx.google.com with ESMTPS id n4-20020a170906688400b00a3173b881aasi561116ejr.4.2024.02.01.23.25.41 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Feb 2024 23:25:41 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-49365-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) client-ip=147.75.80.249; Authentication-Results: mx.google.com; dkim=pass header.i=@endlessos.org header.s=google header.b=c7TQfoqV; arc=pass (i=1 spf=pass spfdomain=endlessos.org dkim=pass dkdomain=endlessos.org dmarc=pass fromdomain=endlessos.org); spf=pass (google.com: domain of linux-kernel+bounces-49365-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.80.249 as permitted sender) smtp.mailfrom="linux-kernel+bounces-49365-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=endlessos.org Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by am.mirrors.kernel.org (Postfix) with ESMTPS id 3E81D1F23BC2 for <ouuuleilei@gmail.com>; Fri, 2 Feb 2024 07:25:41 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E888417BD9; Fri, 2 Feb 2024 07:25:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=endlessos.org header.i=@endlessos.org header.b="c7TQfoqV" Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0093517C67 for <linux-kernel@vger.kernel.org>; Fri, 2 Feb 2024 07:25:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706858720; cv=none; b=UyKzb79wNsuBvP2npMCxVQX7n1LCy/iObl60A8mR7cquO466RUGWgf7f2Ep56+N76NbbdiLCGGi4xtJZBqPjoo1SCt061P6R8H/nMTZvbkP4LA5JS2rvwqUrFvhTd4fsH2oGilhv4Z7M5806djIVpGqTlLo1YrOk592PqwzjKic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706858720; c=relaxed/simple; bh=wNy7U7w8pWIL0zpi8DS9mnETjYx9lJhJ8VvkKcLixVU=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=BbhbnMoaVzQE/7fh3s1t+DiJqTQmiIbNsft80mNfvU8GYmvvvp3J4VDzQJu5e0o1wZ+tga3/LyCyDiamPQA+J8S15iRwM4HdtdKyP1yutMG6bVYCYdsvVAXW74AMRdzvkl9a+qbEMuqYICi5RpTT9chanUCSgwQgSE1GIYWGOJE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=endlessos.org; spf=pass smtp.mailfrom=endlessos.org; dkim=pass (2048-bit key) header.d=endlessos.org header.i=@endlessos.org header.b=c7TQfoqV; arc=none smtp.client-ip=209.85.210.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=endlessos.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=endlessos.org Received: by mail-pf1-f175.google.com with SMTP id d2e1a72fcca58-6da4a923b1bso1211821b3a.2 for <linux-kernel@vger.kernel.org>; Thu, 01 Feb 2024 23:25:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=endlessos.org; s=google; t=1706858718; x=1707463518; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=NZkIYyyqlYFNT1lqciy923TmN3UIp12qeGkpjnu4yVM=; b=c7TQfoqVEjujc+cnxMubtFZZHzW81mzAjzkPKKcXH/+FLWfYRsbWrPOyQuYK0hcTrp loyByqcPrHgIg49TzlGa8CnqJDtooLleJ+7fdiFoCDLIp8ewWQj8zuoKiJY55iasow6w z0AJF1qQt6mBzm/J42DIH2hgbP/QOp/4oOdyiqEZ6PODuJEylGBZeL9dmHFp27wJKotF NuXMk9YygR4SKjz1+Mmx53zyc6XIEi26YxBr5Ss9Lyf4R1K5kn1Lg6a8MEpmbGH3saE5 a1gz0OOANHSX5AnbqBCz5dyAiIXXS6D9H8MdYUEFvIwpR/4CCVh3ly97v7icQMUaD7NH O5VA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706858718; x=1707463518; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=NZkIYyyqlYFNT1lqciy923TmN3UIp12qeGkpjnu4yVM=; b=ovkTAHLAYYWWhyzHJkvbcfbQvkWxOW5RS8ePH3WzeUTTyGbBuLPpHxHtCpbKp8H2aT bP7pXmz3/d0YpodznShs7J40NO0BqJMY4pl1F71e1z1HiyVPtBkrPNEwnTKXyRQxml10 ikav2INgKWzHn5gWYAISLPtZ3xR5PDICDDqatlpKiWFuFXqDsf7awJ90mGkBDNLUX5x6 NyI3s1mKOhCAkyJNKR2YKcyQ2vpxCwzEg6POSdB1JECNUTgR9GwHF2wMPqjTD0eZWTjH 36W0XbmgYaIoj7Pjly/anCgGjY6b292z0AfSyFsrtBQWkmpx/UB77VwhQbHdg1Qi4HT/ yPGw== X-Gm-Message-State: AOJu0YwzvP6a8N/tXmtliS7CediCiR9LRhdmMRNueL0SGCAphL5scSGz Bq0/nd35QbYoltQA4jRk5glYcEwnSjcx9IehyP0yvz8zYI7YdNzaEvr/pv7yD2J8/0Unl1EMSrn N X-Received: by 2002:a05:6a20:af89:b0:19c:88c1:1878 with SMTP id ds9-20020a056a20af8900b0019c88c11878mr4212107pzb.23.1706858718122; Thu, 01 Feb 2024 23:25:18 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCW33KELekP8WYe+iZAXFFMvFoCBk0C5ZZtWotl0dqjYvtmozg13QTMdM/pGnDv/1JcKO0b7ZsfuW8a0Xsoi0UFKx4PuJO8witn5E7aL7ebOXdkXWWiPb0jzZFzaD4krM/UOQnxRQfwFD9DXgVc4WympW+kYpL9t3bQwfAwSp0u8h3ez1ibP83pZIbprpwMdEhPGFoNR1PA1BazQBgZAJTcCu2/a8pEFyW1pd5sNTdfMg4DYFwDQ/UdxEm1NpgGVupVKpz9xg6WAiYannEYX4x+g+atYU1sVnWIVmeWt8oJn212fTyX7a4hxmCRDU1ghXMFFGM4R7f33oWBg+PDQSf76tC2UCyKg3gIwTBHS9+sA7ms8/QzGbeqYE0vOTrnv3g== Received: from localhost.localdomain ([123.51.167.56]) by smtp.googlemail.com with ESMTPSA id fb36-20020a056a002da400b006de39de76adsm907240pfb.139.2024.02.01.23.25.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Feb 2024 23:25:17 -0800 (PST) From: Jian-Hong Pan <jhp@endlessos.org> To: Bjorn Helgaas <helgaas@kernel.org>, Johan Hovold <johan@kernel.org> Cc: Mika Westerberg <mika.westerberg@linux.intel.com>, David Box <david.e.box@linux.intel.com>, Damien Le Moal <dlemoal@kernel.org>, Niklas Cassel <cassel@kernel.org>, Nirmal Patel <nirmal.patel@linux.intel.com>, Jonathan Derrick <jonathan.derrick@linux.dev>, linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux@endlessos.org, Jian-Hong Pan <jhp@endlessos.org> Subject: [PATCH v2] PCI: vmd: Enable PCI PM's L1 substates of remapped PCIe Root Port and NVMe Date: Fri, 2 Feb 2024 15:11:12 +0800 Message-ID: <20240202071110.8515-3-jhp@endlessos.org> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789771112342319978 X-GMAIL-MSGID: 1789771112342319978 |
Series |
[v2] PCI: vmd: Enable PCI PM's L1 substates of remapped PCIe Root Port and NVMe
|
|
Commit Message
Jian-Hong Pan
Feb. 2, 2024, 7:11 a.m. UTC
The remapped PCIe Root Port and NVMe have PCI PM L1 substates
capability, but they are disabled originally:
Here is an example on ASUS B1400CEAE:
Capabilities: [900 v1] L1 PM Substates
L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- L1_PM_Substates+
PortCommonModeRestoreTime=32us PortTPowerOnTime=10us
L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1-
T_CommonMode=0us LTR1.2_Threshold=0ns
L1SubCtl2: T_PwrOn=10us
Power on all of the VMD remapped PCI devices and quirk max snoop LTR
before enable PCI-PM L1 PM Substates by following "Section 5.5.4 of PCIe
Base Spec Revision 6.0". Then, PCI PM's L1 substates control are
initialized & enabled accordingly. Also, update the comments of
pci_enable_link_state() and pci_enable_link_state_locked() for
kernel-doc, too.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=218394
Signed-off-by: Jian-Hong Pan <jhp@endlessos.org>
---
v2:
- Power on the VMD remapped devices with pci_set_power_state_locked()
- Prepare the PCIe LTR parameters before enable L1 Substates
- Add note into the comments of both pci_enable_link_state() and
pci_enable_link_state_locked() for kernel-doc.
- The original patch set can be split as individual patches.
drivers/pci/controller/vmd.c | 15 ++++++++++-----
drivers/pci/pcie/aspm.c | 10 ++++++++++
2 files changed, 20 insertions(+), 5 deletions(-)
Comments
On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > The remapped PCIe Root Port and NVMe have PCI PM L1 substates > capability, but they are disabled originally: > > Here is an example on ASUS B1400CEAE: > > Capabilities: [900 v1] L1 PM Substates > L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- L1_PM_Substates+ > PortCommonModeRestoreTime=32us PortTPowerOnTime=10us > L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- > T_CommonMode=0us LTR1.2_Threshold=0ns > L1SubCtl2: T_PwrOn=10us > > Power on all of the VMD remapped PCI devices and quirk max snoop LTR > before enable PCI-PM L1 PM Substates by following "Section 5.5.4 of PCIe > Base Spec Revision 6.0". Then, PCI PM's L1 substates control are > initialized & enabled accordingly. > Also, update the comments of > pci_enable_link_state() and pci_enable_link_state_locked() for > kernel-doc, too. The aspm.c changes should be in a separate patch. Presumably the aspm.c code change fixes a defect, and that defect can be described in that patch. That fix may be needed for non-VMD situations, and having it in this vmd patch means it won't be as easy to find and backport. Nit: rewrap commit log to fill 75 columns. > @@ -751,11 +751,9 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) > if (!(features & VMD_FEAT_BIOS_PM_QUIRK)) > return 0; > > - pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); > - > pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR); > if (!pos) > - return 0; > + goto out_enable_link_state; > > /* > * Skip if the max snoop LTR is non-zero, indicating BIOS has set it > @@ -763,7 +761,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) > */ > pci_read_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, <r_reg); > if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK))) > - return 0; > + goto out_enable_link_state; > > /* > * Set the default values to the maximum required by the platform to > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg); > pci_info(pdev, "VMD: Default LTR value set by driver\n"); You're not changing this part, and I don't understand exactly how LTR works, but it makes me a little bit queasy to read "set the LTR value to the maximum required to allow the deepest power management savings" and then we set the max snoop values to a fixed constant. I don't think the goal is to "allow the deepest power savings"; I think it's to enable L1.2 *when the device has enough buffering to absorb L1.2 entry/exit latencies*. The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to the platform's maximum supported latency or less," so it seems like that value must be platform-dependent, not fixed. And I assume the "_DSM for Latency Tolerance Reporting" is part of the way to get those platform-dependent values, but Linux doesn't actually use that yet. I assume that setting the max values incorrectly may lead to either being too conservative, so we don't use L1.2 when we could, or too aggressive, so we use L1.2 when we shouldn't, and the device loses data because it doesn't have enough internal buffering to absorb the entry/exit delays. This paper has a lot of background and might help answer some of my questions: https://www.intel.co.za/content/dam/doc/white-paper/energy-efficient-platforms-white-paper.pdf > +out_enable_link_state: > + /* > + * Make PCI devices at D0 when enable PCI-PM L1 PM Substates from > + * Section 5.5.4 of PCIe Base Spec Revision 6.0 > + */ > + pci_set_power_state_locked(pdev, PCI_D0); > + pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); Hmmm. PCIE_LINK_STATE_ALL includes ASPM L1.2. We may do this even if the device doesn't have an LTR Capability. ASPM L1.2 cannot work without LTR. I only took a quick look but was not convinced that pci_enable_link_state() does the right thing when we enable PCIE_LINK_STATE_ALL (including ASPM L1.2) on a device that doesn't have LTR. I think it *should* decline to set PCI_L1SS_CTL1_ASPM_L1_2, but I'm not sure it does. Can you double check that path? Maybe that's another defect in aspm.c. > @@ -1164,6 +1164,8 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked) > link->aspm_default |= ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1; > if (state & PCIE_LINK_STATE_L1_2_PCIPM) > link->aspm_default |= ASPM_STATE_L1_2_PCIPM | ASPM_STATE_L1; > + if (state & ASPM_STATE_L1_2_MASK) > + aspm_l1ss_init(link); > pcie_config_aspm_link(link, policy_to_aspm_state(link)); > > link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
On Fri, 2024-02-02 at 18:05 -0600, Bjorn Helgaas wrote: > On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > > The remapped PCIe Root Port and NVMe have PCI PM L1 substates > > capability, but they are disabled originally: > > > > Here is an example on ASUS B1400CEAE: > > > > Capabilities: [900 v1] L1 PM Substates > > L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- > > L1_PM_Substates+ > > PortCommonModeRestoreTime=32us PortTPowerOnTime=10us > > L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- > > T_CommonMode=0us LTR1.2_Threshold=0ns > > L1SubCtl2: T_PwrOn=10us > > > > Power on all of the VMD remapped PCI devices and quirk max snoop LTR > > before enable PCI-PM L1 PM Substates by following "Section 5.5.4 of PCIe > > Base Spec Revision 6.0". Then, PCI PM's L1 substates control are > > initialized & enabled accordingly. > > > Also, update the comments of > > pci_enable_link_state() and pci_enable_link_state_locked() for > > kernel-doc, too. > > The aspm.c changes should be in a separate patch. Presumably the > aspm.c code change fixes a defect, and that defect can be described in > that patch. That fix may be needed for non-VMD situations, and having > it in this vmd patch means it won't be as easy to find and backport. > > Nit: rewrap commit log to fill 75 columns. > > > @@ -751,11 +751,9 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, > > void *userdata) > > if (!(features & VMD_FEAT_BIOS_PM_QUIRK)) > > return 0; > > > > - pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); > > - > > pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR); > > if (!pos) > > - return 0; > > + goto out_enable_link_state; > > > > /* > > * Skip if the max snoop LTR is non-zero, indicating BIOS has set > > it > > @@ -763,7 +761,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, > > void *userdata) > > */ > > pci_read_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, <r_reg); > > if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK))) > > - return 0; > > + goto out_enable_link_state; > > > > /* > > * Set the default values to the maximum required by the platform > > to > > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, > > void *userdata) > > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg); > > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > You're not changing this part, and I don't understand exactly how LTR > works, but it makes me a little bit queasy to read "set the LTR value > to the maximum required to allow the deepest power management > savings" and then we set the max snoop values to a fixed constant. > > I don't think the goal is to "allow the deepest power savings"; I > think it's to enable L1.2 *when the device has enough buffering to > absorb L1.2 entry/exit latencies*. > > The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to > the platform's maximum supported latency or less," so it seems like > that value must be platform-dependent, not fixed. > > And I assume the "_DSM for Latency Tolerance Reporting" is part of the > way to get those platform-dependent values, but Linux doesn't actually > use that yet. This may indeed be the best way but we need to double check with our BIOS folks. AFAIK BIOS writes the LTR values directly so there hasn't been a need to use this _DSM. But under VMD the ports are hidden from BIOS which is why we added it here. I've brought up the question internally to find out how Windows handles the DSM and to get a recommendation from our firmware leads. > > I assume that setting the max values incorrectly may lead to either > being too conservative, so we don't use L1.2 when we could, or too > aggressive, so we use L1.2 when we shouldn't, and the device loses > data because it doesn't have enough internal buffering to absorb the > entry/exit delays. > > This paper has a lot of background and might help answer some of my > questions: > https://www.intel.co.za/content/dam/doc/white-paper/energy-efficient-platforms-white-paper.pdf > > > +out_enable_link_state: > > + /* > > + * Make PCI devices at D0 when enable PCI-PM L1 PM Substates from > > + * Section 5.5.4 of PCIe Base Spec Revision 6.0 > > + */ > > + pci_set_power_state_locked(pdev, PCI_D0); > > + pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); > > Hmmm. PCIE_LINK_STATE_ALL includes ASPM L1.2. We may do this even if > the device doesn't have an LTR Capability. ASPM L1.2 cannot work > without LTR. > > I only took a quick look but was not convinced that > pci_enable_link_state() does the right thing when we enable > PCIE_LINK_STATE_ALL (including ASPM L1.2) on a device that doesn't > have LTR. I think it *should* decline to set PCI_L1SS_CTL1_ASPM_L1_2, > but I'm not sure it does. Can you double check that path? Maybe > that's another defect in aspm.c. It doesn't currently decline. The same scenario happens when the user selects powersupersave. If a device advertises L1.2 with the capable registers set, it should also have the LTR register present. But it doesn't hurt to check. David > > > @@ -1164,6 +1164,8 @@ static int __pci_enable_link_state(struct pci_dev > > *pdev, int state, bool locked) > > link->aspm_default |= ASPM_STATE_L1_1_PCIPM | > > ASPM_STATE_L1; > > if (state & PCIE_LINK_STATE_L1_2_PCIPM) > > link->aspm_default |= ASPM_STATE_L1_2_PCIPM | > > ASPM_STATE_L1; > > + if (state & ASPM_STATE_L1_2_MASK) > > + aspm_l1ss_init(link); > > pcie_config_aspm_link(link, policy_to_aspm_state(link)); > > > > link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
On Mon, Feb 05, 2024 at 11:37:16AM -0800, David E. Box wrote: > On Fri, 2024-02-02 at 18:05 -0600, Bjorn Helgaas wrote: > > On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > ... > > > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, > > > void *userdata) > > > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg); > > > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > > > You're not changing this part, and I don't understand exactly how LTR > > works, but it makes me a little bit queasy to read "set the LTR value > > to the maximum required to allow the deepest power management > > savings" and then we set the max snoop values to a fixed constant. > > > > I don't think the goal is to "allow the deepest power savings"; I > > think it's to enable L1.2 *when the device has enough buffering to > > absorb L1.2 entry/exit latencies*. > > > > The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to > > the platform's maximum supported latency or less," so it seems like > > that value must be platform-dependent, not fixed. > > > > And I assume the "_DSM for Latency Tolerance Reporting" is part of the > > way to get those platform-dependent values, but Linux doesn't actually > > use that yet. > > This may indeed be the best way but we need to double check with our > BIOS folks. AFAIK BIOS writes the LTR values directly so there > hasn't been a need to use this _DSM. But under VMD the ports are > hidden from BIOS which is why we added it here. I've brought up the > question internally to find out how Windows handles the DSM and to > get a recommendation from our firmware leads. We want Linux to be able to program LTR itself, don't we? We shouldn't have to rely on firmware to do it. If Linux can't do it, hot-added devices aren't going to be able to use L1.2, right? Bjorn
On Mon, 2024-02-05 at 16:42 -0600, Bjorn Helgaas wrote: > On Mon, Feb 05, 2024 at 11:37:16AM -0800, David E. Box wrote: > > On Fri, 2024-02-02 at 18:05 -0600, Bjorn Helgaas wrote: > > > On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > > ... > > > > > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev > > > > *pdev, > > > > void *userdata) > > > > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, > > > > ltr_reg); > > > > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > > > > > You're not changing this part, and I don't understand exactly how LTR > > > works, but it makes me a little bit queasy to read "set the LTR value > > > to the maximum required to allow the deepest power management > > > savings" and then we set the max snoop values to a fixed constant. > > > > > > I don't think the goal is to "allow the deepest power savings"; I > > > think it's to enable L1.2 *when the device has enough buffering to > > > absorb L1.2 entry/exit latencies*. > > > > > > The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to > > > the platform's maximum supported latency or less," so it seems like > > > that value must be platform-dependent, not fixed. > > > > > > And I assume the "_DSM for Latency Tolerance Reporting" is part of the > > > way to get those platform-dependent values, but Linux doesn't actually > > > use that yet. > > > > This may indeed be the best way but we need to double check with our > > BIOS folks. AFAIK BIOS writes the LTR values directly so there > > hasn't been a need to use this _DSM. But under VMD the ports are > > hidden from BIOS which is why we added it here. I've brought up the > > question internally to find out how Windows handles the DSM and to > > get a recommendation from our firmware leads. > > We want Linux to be able to program LTR itself, don't we? We > shouldn't have to rely on firmware to do it. If Linux can't do > it, hot-added devices aren't going to be able to use L1.2, right? Agreed. We just want to make sure we are not conflicting with what BIOS may be doing. David
On Fri, 2 Feb 2024, Jian-Hong Pan wrote: > The remapped PCIe Root Port and NVMe have PCI PM L1 substates > capability, but they are disabled originally: > > Here is an example on ASUS B1400CEAE: > > Capabilities: [900 v1] L1 PM Substates > L1SubCap: PCI-PM_L1.2+ PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- L1_PM_Substates+ > PortCommonModeRestoreTime=32us PortTPowerOnTime=10us > L1SubCtl1: PCI-PM_L1.2- PCI-PM_L1.1- ASPM_L1.2+ ASPM_L1.1- > T_CommonMode=0us LTR1.2_Threshold=0ns > L1SubCtl2: T_PwrOn=10us > > Power on all of the VMD remapped PCI devices and quirk max snoop LTR > before enable PCI-PM L1 PM Substates by following "Section 5.5.4 of PCIe > Base Spec Revision 6.0". Then, PCI PM's L1 substates control are > initialized & enabled accordingly. Also, update the comments of > pci_enable_link_state() and pci_enable_link_state_locked() for > kernel-doc, too. > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=218394 > Signed-off-by: Jian-Hong Pan <jhp@endlessos.org> > --- > v2: > - Power on the VMD remapped devices with pci_set_power_state_locked() > - Prepare the PCIe LTR parameters before enable L1 Substates > - Add note into the comments of both pci_enable_link_state() and > pci_enable_link_state_locked() for kernel-doc. > - The original patch set can be split as individual patches. > > drivers/pci/controller/vmd.c | 15 ++++++++++----- > drivers/pci/pcie/aspm.c | 10 ++++++++++ > 2 files changed, 20 insertions(+), 5 deletions(-) > > diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c > index 87b7856f375a..66e47a0dbf1a 100644 > --- a/drivers/pci/controller/vmd.c > +++ b/drivers/pci/controller/vmd.c > @@ -751,11 +751,9 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) > if (!(features & VMD_FEAT_BIOS_PM_QUIRK)) > return 0; > > - pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); > - > pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR); > if (!pos) > - return 0; > + goto out_enable_link_state; > > /* > * Skip if the max snoop LTR is non-zero, indicating BIOS has set it > @@ -763,7 +761,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) > */ > pci_read_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, <r_reg); > if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK))) > - return 0; > + goto out_enable_link_state; > > /* > * Set the default values to the maximum required by the platform to > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg); > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > +out_enable_link_state: > + /* > + * Make PCI devices at D0 when enable PCI-PM L1 PM Substates from > + * Section 5.5.4 of PCIe Base Spec Revision 6.0 I don't understand what are you trying to say here? Are there some typos or grammar errors or something entire missing from the comment? > + */ > + pci_set_power_state_locked(pdev, PCI_D0); > + pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); > + > return 0; > } > > @@ -926,7 +932,6 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) > dev_get_msi_domain(&vmd->dev->dev)); > > vmd_acpi_begin(); > - > pci_scan_child_bus(vmd->bus); > vmd_domain_reset(vmd); Spurious newline change.
Adding Puranjay On Mon, 2024-02-05 at 15:05 -0800, David E. Box wrote: > On Mon, 2024-02-05 at 16:42 -0600, Bjorn Helgaas wrote: > > On Mon, Feb 05, 2024 at 11:37:16AM -0800, David E. Box wrote: > > > On Fri, 2024-02-02 at 18:05 -0600, Bjorn Helgaas wrote: > > > > On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > > > ... > > > > > > > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev > > > > > *pdev, > > > > > void *userdata) > > > > > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, > > > > > ltr_reg); > > > > > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > > > > > > > You're not changing this part, and I don't understand exactly how LTR > > > > works, but it makes me a little bit queasy to read "set the LTR value > > > > to the maximum required to allow the deepest power management > > > > savings" and then we set the max snoop values to a fixed constant. > > > > > > > > I don't think the goal is to "allow the deepest power savings"; I > > > > think it's to enable L1.2 *when the device has enough buffering to > > > > absorb L1.2 entry/exit latencies*. > > > > > > > > The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to > > > > the platform's maximum supported latency or less," so it seems like > > > > that value must be platform-dependent, not fixed. > > > > > > > > And I assume the "_DSM for Latency Tolerance Reporting" is part of the > > > > way to get those platform-dependent values, but Linux doesn't actually > > > > use that yet. > > > > > > This may indeed be the best way but we need to double check with our > > > BIOS folks. AFAIK BIOS writes the LTR values directly so there > > > hasn't been a need to use this _DSM. But under VMD the ports are > > > hidden from BIOS which is why we added it here. I've brought up the > > > question internally to find out how Windows handles the DSM and to > > > get a recommendation from our firmware leads. > > > > We want Linux to be able to program LTR itself, don't we? We > > shouldn't have to rely on firmware to do it. If Linux can't do > > it, hot-added devices aren't going to be able to use L1.2, right? > > Agreed. We just want to make sure we are not conflicting with what BIOS may be > doing. So the feedback is to run the _DSM and just overwrite any BIOS values. Looking up the _DSM I saw there was an attempt to upstream this 4 years ago [1]. I'm not sure why the effort stalled but we can pick up this work again. https://patchwork.kernel.org/project/linux-pci/patch/20201015080311.7811-1-puranjay12@gmail.com/
On Tue, Feb 06, 2024 at 01:25:29PM -0800, David E. Box wrote: > On Mon, 2024-02-05 at 15:05 -0800, David E. Box wrote: > > On Mon, 2024-02-05 at 16:42 -0600, Bjorn Helgaas wrote: > > > On Mon, Feb 05, 2024 at 11:37:16AM -0800, David E. Box wrote: > > > > On Fri, 2024-02-02 at 18:05 -0600, Bjorn Helgaas wrote: > > > > > On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > > > > ... > > > > > > > > > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev > > > > > > *pdev, > > > > > > void *userdata) > > > > > > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, > > > > > > ltr_reg); > > > > > > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > > > > > > > > > You're not changing this part, and I don't understand exactly how LTR > > > > > works, but it makes me a little bit queasy to read "set the LTR value > > > > > to the maximum required to allow the deepest power management > > > > > savings" and then we set the max snoop values to a fixed constant. > > > > > > > > > > I don't think the goal is to "allow the deepest power savings"; I > > > > > think it's to enable L1.2 *when the device has enough buffering to > > > > > absorb L1.2 entry/exit latencies*. > > > > > > > > > > The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to > > > > > the platform's maximum supported latency or less," so it seems like > > > > > that value must be platform-dependent, not fixed. > > > > > > > > > > And I assume the "_DSM for Latency Tolerance Reporting" is part of the > > > > > way to get those platform-dependent values, but Linux doesn't actually > > > > > use that yet. > > > > > > > > This may indeed be the best way but we need to double check with our > > > > BIOS folks. AFAIK BIOS writes the LTR values directly so there > > > > hasn't been a need to use this _DSM. But under VMD the ports are > > > > hidden from BIOS which is why we added it here. I've brought up the > > > > question internally to find out how Windows handles the DSM and to > > > > get a recommendation from our firmware leads. > > > > > > We want Linux to be able to program LTR itself, don't we? We > > > shouldn't have to rely on firmware to do it. If Linux can't do > > > it, hot-added devices aren't going to be able to use L1.2, > > > right? > > > > Agreed. We just want to make sure we are not conflicting with what > > BIOS may be doing. > > So the feedback is to run the _DSM and just overwrite any BIOS > values. Looking up the _DSM I saw there was an attempt to upstream > this 4 years ago [1]. I'm not sure why the effort stalled but we can > pick up this work again. > > https://patchwork.kernel.org/project/linux-pci/patch/20201015080311.7811-1-puranjay12@gmail.com/ There was a PCI SIG discussion about this a few years ago that never really seemed to get resolved: https://members.pcisig.com/wg/PCIe-Protocol/mail/thread/35064 Unfortunately that discussion is not public, but the summary is: Q: How is the LTR_L1.2_THRESHOLD value determined? PCIe r5.0, sec 5.5.4, says the same value must be programmed into both Ports. A: As noted in sec 5.5.4, the value is determined primarily by the amount of time it will take to re-establish the common mode bias on the AC coupling caps, and it is assumed that the BIOS knows this. Q: How are the LTR Max Snoop values determined? PCI Firmware r3.3, sec 4.6.6, says the LTR _DSM reports the max values for each Downstream Port embedded in the platform, and the OS should calculate latencies along the path between each Downstream Port and any Upstream Port (Switch Upstream Port or Endpoint). Of course, Switches not embedded in the platform (e.g., external Thunderbolt hierarchies) will not have this _DSM, but I assume they should contribute to this sum? A: The fundamental problem is that there is no practical way for software to discover the AC coupling capacitor sizes and common mode bias circuit impedance. Software could compute conservative values, but they would likely be 10x worse than typical, so the L1.2 exit latency would be significantly longer than actually required to be. The interoperability issues here were understood when designing L1 Substates, but no viable solution was found. So the main reason Puranjay's work got stalled is that I didn't feel confident enough that we understood how to do this, especially for external devices. It would be great if somebody *did* feel confident about interpreting and implementing all this. Bjorn
On Tue, 2024-02-06 at 17:30 -0600, Bjorn Helgaas wrote: > On Tue, Feb 06, 2024 at 01:25:29PM -0800, David E. Box wrote: > > On Mon, 2024-02-05 at 15:05 -0800, David E. Box wrote: > > > On Mon, 2024-02-05 at 16:42 -0600, Bjorn Helgaas wrote: > > > > On Mon, Feb 05, 2024 at 11:37:16AM -0800, David E. Box wrote: > > > > > On Fri, 2024-02-02 at 18:05 -0600, Bjorn Helgaas wrote: > > > > > > On Fri, Feb 02, 2024 at 03:11:12PM +0800, Jian-Hong Pan wrote: > > > > > ... > > > > > > > > > > > @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev > > > > > > > *pdev, > > > > > > > void *userdata) > > > > > > > pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, > > > > > > > ltr_reg); > > > > > > > pci_info(pdev, "VMD: Default LTR value set by driver\n"); > > > > > > > > > > > > You're not changing this part, and I don't understand exactly how > > > > > > LTR > > > > > > works, but it makes me a little bit queasy to read "set the LTR > > > > > > value > > > > > > to the maximum required to allow the deepest power management > > > > > > savings" and then we set the max snoop values to a fixed constant. > > > > > > > > > > > > I don't think the goal is to "allow the deepest power savings"; I > > > > > > think it's to enable L1.2 *when the device has enough buffering to > > > > > > absorb L1.2 entry/exit latencies*. > > > > > > > > > > > > The spec (PCIe r6.0, sec 7.8.2.2) says "Software should set this to > > > > > > the platform's maximum supported latency or less," so it seems like > > > > > > that value must be platform-dependent, not fixed. > > > > > > > > > > > > And I assume the "_DSM for Latency Tolerance Reporting" is part of > > > > > > the > > > > > > way to get those platform-dependent values, but Linux doesn't > > > > > > actually > > > > > > use that yet. > > > > > > > > > > This may indeed be the best way but we need to double check with our > > > > > BIOS folks. AFAIK BIOS writes the LTR values directly so there > > > > > hasn't been a need to use this _DSM. But under VMD the ports are > > > > > hidden from BIOS which is why we added it here. I've brought up the > > > > > question internally to find out how Windows handles the DSM and to > > > > > get a recommendation from our firmware leads. > > > > > > > > We want Linux to be able to program LTR itself, don't we? We > > > > shouldn't have to rely on firmware to do it. If Linux can't do > > > > it, hot-added devices aren't going to be able to use L1.2, > > > > right? > > > > > > Agreed. We just want to make sure we are not conflicting with what > > > BIOS may be doing. > > > > So the feedback is to run the _DSM and just overwrite any BIOS > > values. Looking up the _DSM I saw there was an attempt to upstream > > this 4 years ago [1]. I'm not sure why the effort stalled but we can > > pick up this work again. > > > > https://patchwork.kernel.org/project/linux-pci/patch/20201015080311.7811-1-puranjay12@gmail.com/ > > There was a PCI SIG discussion about this a few years ago that never > really seemed to get resolved: > https://members.pcisig.com/wg/PCIe-Protocol/mail/thread/35064 > > Unfortunately that discussion is not public, but the summary is: > > Q: How is the LTR_L1.2_THRESHOLD value determined? > > PCIe r5.0, sec 5.5.4, says the same value must be programmed into > both Ports. > > A: As noted in sec 5.5.4, the value is determined primarily by > the amount of time it will take to re-establish the common > mode bias on the AC coupling caps, and it is assumed that the > BIOS knows this. > > Q: How are the LTR Max Snoop values determined? > > PCI Firmware r3.3, sec 4.6.6, says the LTR _DSM reports the max > values for each Downstream Port embedded in the platform, and the > OS should calculate latencies along the path between each > Downstream Port and any Upstream Port (Switch Upstream Port or > Endpoint). > > Of course, Switches not embedded in the platform (e.g., external > Thunderbolt hierarchies) will not have this _DSM, but I assume > they should contribute to this sum? > > A: The fundamental problem is that there is no practical way for > software to discover the AC coupling capacitor sizes and > common mode bias circuit impedance. > > Software could compute conservative values, but they would > likely be 10x worse than typical, so the L1.2 exit latency > would be significantly longer than actually required to be. > > The interoperability issues here were understood when > designing L1 Substates, but no viable solution was found. > > So the main reason Puranjay's work got stalled is that I didn't feel > confident enough that we understood how to do this, especially for > external devices. > > It would be great if somebody *did* feel confident about interpreting > and implementing all this. As it is BIOS (at least Intel BIOS) is already writing the maximum allowed LTR value on Upstream Ports that have it set to 0. So we can't do any worse if we write the BIOS provided _DSM value for all Upstream Ports, including external devices. Sounds like the worst case scenario is that devices take longer than needed to exit L1.2 (I'm still asking about this detail). But I think this is better than not programming the LTR at all which could prevent the platform from power gating they very resources that LTR is meant to help manage. If that reasoning is okay with you, I'll submit patches to use the _DSM. David
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c index 87b7856f375a..66e47a0dbf1a 100644 --- a/drivers/pci/controller/vmd.c +++ b/drivers/pci/controller/vmd.c @@ -751,11 +751,9 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) if (!(features & VMD_FEAT_BIOS_PM_QUIRK)) return 0; - pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR); if (!pos) - return 0; + goto out_enable_link_state; /* * Skip if the max snoop LTR is non-zero, indicating BIOS has set it @@ -763,7 +761,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) */ pci_read_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, <r_reg); if (!!(ltr_reg & (PCI_LTR_VALUE_MASK | PCI_LTR_SCALE_MASK))) - return 0; + goto out_enable_link_state; /* * Set the default values to the maximum required by the platform to @@ -775,6 +773,14 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata) pci_write_config_dword(pdev, pos + PCI_LTR_MAX_SNOOP_LAT, ltr_reg); pci_info(pdev, "VMD: Default LTR value set by driver\n"); +out_enable_link_state: + /* + * Make PCI devices at D0 when enable PCI-PM L1 PM Substates from + * Section 5.5.4 of PCIe Base Spec Revision 6.0 + */ + pci_set_power_state_locked(pdev, PCI_D0); + pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL); + return 0; } @@ -926,7 +932,6 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features) dev_get_msi_domain(&vmd->dev->dev)); vmd_acpi_begin(); - pci_scan_child_bus(vmd->bus); vmd_domain_reset(vmd); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index bc0bd86695ec..5f902c5552ca 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1164,6 +1164,8 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked) link->aspm_default |= ASPM_STATE_L1_1_PCIPM | ASPM_STATE_L1; if (state & PCIE_LINK_STATE_L1_2_PCIPM) link->aspm_default |= ASPM_STATE_L1_2_PCIPM | ASPM_STATE_L1; + if (state & ASPM_STATE_L1_2_MASK) + aspm_l1ss_init(link); pcie_config_aspm_link(link, policy_to_aspm_state(link)); link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0; @@ -1182,6 +1184,10 @@ static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked) * touch the LNKCTL register. Also note that this does not enable states * disabled by pci_disable_link_state(). Return 0 or a negative errno. * + * Note: The PCIe devices of the link must be in D0, if the PCI-PM L1 PM + * substates are going to be enabled. From Section 5.5.4 of PCIe Base Spec + * Revision 6.0. + * * @pdev: PCI device * @state: Mask of ASPM link states to enable */ @@ -1198,6 +1204,10 @@ EXPORT_SYMBOL(pci_enable_link_state); * can't touch the LNKCTL register. Also note that this does not enable states * disabled by pci_disable_link_state(). Return 0 or a negative errno. * + * Note: The PCIe devices of the link must be in D0, if the PCI-PM L1 PM + * substates are going to be enabled. From Section 5.5.4 of PCIe Base Spec + * Revision 6.0. + * * @pdev: PCI device * @state: Mask of ASPM link states to enable *