Received: by 2002:ac0:a5b6:0:0:0:0:0 with SMTP id m51-v6csp4713467imm; Wed, 30 May 2018 10:28:39 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJx1hF5B6czVgyNQFmFvlmz0H1SuaG1qFW5y9CN3Omdm07Ef72kBHChsJ+rTZHorg9qQDC4 X-Received: by 2002:a62:9e0b:: with SMTP id s11-v6mr3610230pfd.198.1527701319121; Wed, 30 May 2018 10:28:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1527701319; cv=none; d=google.com; s=arc-20160816; b=masYK1o/VU0sHkm7v3YbZdiW/C5ZEnbCp/XQ1T1eRiOKDh4xha8nnYHnE1JqqrSwBm DPM5nTB0pLtvgwiX8EQKaiivsoZ2ZWcnXt0MssHRLZ2Tpe1NjaPRK+Xi3YLAUlQPkmRf IJj2Rz1olMT55pJ8kIrU+xunYCXCXBCUaqOL3Wfl0ea7X9S+1YMS3nWrWmi3nokMojSQ rMuI2Wt/ffpEAMvZcmxlUrO+pQG8G+nh5bpRNw0pUR9F0T5C150gtaKCWO3zue7CU3iH S0jsUp3A/ISM+s7USVe8aQxCuNm2p9iECHUKY7DZxSFXBwkYaHgCzpcB2XUT7dJEDNYq 1Tuw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:user-agent:in-reply-to :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:dkim-signature:arc-authentication-results; bh=KeatE9XXfZAxeLRfqhf/pT1RUQNWC4rfqpw2VABzgvI=; b=S+siKoHXffA/IbXLGC6df9dVI1lwKTUiqJOGXUaSRvtv+O9SS4BSXeRwc+jl7nTfdc r0W9dOvBh+dIZeWdrDmu1mYzNMWs+e09/qj5gLfK6RDcad+5cjO0TGZXgKTIBwuV8D8e DF2vdNZhKqbSgRTzsSb2dc8AF4yYrzk3IFALKEbhkjBpQdYRmVNVbMkYDA0PaY4z2X75 Xm5F1tXtiJhiyDDSvBLvhgkmq/zYmwbS6MG6NG9xAgbVl4/hps4W/927sWa65HITnQIw 2bAA8llFaH6b9obY+7KS+zJnSZaOkynJtZZsThKodFtjfyXuKtu3ljGxYoCRH0sTcry9 GXwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=ucbMQu/a; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g12-v6si34762924pla.194.2018.05.30.10.28.24; Wed, 30 May 2018 10:28:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=ucbMQu/a; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753869AbeE3R1l (ORCPT + 99 others); Wed, 30 May 2018 13:27:41 -0400 Received: from mail.kernel.org ([198.145.29.99]:35288 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753604AbeE3R1j (ORCPT ); Wed, 30 May 2018 13:27:39 -0400 Received: from localhost (unknown [104.133.8.78]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DCB0D20881; Wed, 30 May 2018 17:27:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1527701259; bh=eldVlJTk6lPOnaWVrfwocfmIBZxlB3LYzpBty2jxQ50=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=ucbMQu/aUsqohh3J+1IPhYQp/soFP60QiGrY7DIbEH4fAc3+Od7L+5ckbfZnuDqTh On3VV4AP1vfvGOo9/Ld8ZKLxyYr7v7Lh61K7RW5feuZeYGBOq/bINRonVYCuNr8NAQ tjayIFn7srIOLs0cizMTUp1u1gO9ZkDrnAuAgxes= Date: Wed, 30 May 2018 12:27:33 -0500 From: Bjorn Helgaas To: Ray Jui Cc: Bjorn Helgaas , Lorenzo Pieralisi , linux-kernel@vger.kernel.org, bcm-kernel-feedback-list@broadcom.com, linux-pci@vger.kernel.org, Ray Jui Subject: Re: [PATCH INTERNAL 2/3] PCI: iproc: Fix up corrupted PAXC root complex config registers Message-ID: <20180530172733.GN39853@bhelgaas-glaptop.roam.corp.google.com> References: <1526577692-21104-1-git-send-email-ray.jui@broadcom.com> <1526577692-21104-3-git-send-email-ray.jui@broadcom.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1526577692-21104-3-git-send-email-ray.jui@broadcom.com> User-Agent: Mutt/1.9.2 (2017-12-15) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, May 17, 2018 at 10:21:31AM -0700, Ray Jui wrote: > On certain versions of Broadcom PAXC based root complexes, certain > regions of the configuration space are corrupted. As a result, it > prevents the Linux PCIe stack from traversing the linked list of the > capability registers completely and therefore the root complex is > not advertised as "PCIe capable". This prevents the correct PCIe RID > from being parsed in the kernel PCIe stack. A correct RID is required > for mapping to a stream ID from the SMMU or the device ID from the > GICv3 ITS > > This patch fixes up the issue by manually populating the related > PCIe capabilities based on readings from the PCIe capability structure > > Signed-off-by: Ray Jui > Reviewed-by: Anup Patel > Reviewed-by: Scott Branden > --- > drivers/pci/quirks.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 95 insertions(+) > > diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c > index 47dfea0..0cdbd0a 100644 > --- a/drivers/pci/quirks.c > +++ b/drivers/pci/quirks.c > @@ -2198,6 +2198,101 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16f0, quirk_paxc_bridge); > DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd750, quirk_paxc_bridge); > DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd802, quirk_paxc_bridge); > DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd804, quirk_paxc_bridge); > + > +/* > + * The PCI capabilities list for certain revisions of Broadcom PAXC root > + * complexes is incorrectly terminated due to corrupted configuration space > + * registers in the range of 0x50 - 0x5f > + * > + * As a result, the capability list becomes broken and prevent standard PCI > + * stack from being able to traverse to the PCIe capability structure > + */ > +static void quirk_paxc_pcie_capability(struct pci_dev *pdev) > +{ > + int pos, i = 0; > + u8 next_cap; > + u16 reg16, *cap; > + struct pci_cap_saved_state *state; > + > + /* bail out if PCIe capability can be found */ > + if (pdev->pcie_cap || pci_find_capability(pdev, PCI_CAP_ID_EXP)) > + return; > + > + /* locate the power management capability */ > + pos = pci_find_capability(pdev, PCI_CAP_ID_PM); > + if (!pos) > + return; > + > + /* bail out if the next capability pointer is not 0x50/0x58 */ > + pci_read_config_byte(pdev, pos + 1, &next_cap); > + if (next_cap != 0x50 && next_cap != 0x58) > + return; > + > + /* bail out if we do not terminate at 0x50/0x58 */ > + pos = next_cap; > + pci_read_config_byte(pdev, pos + 1, &next_cap); > + if (next_cap != 0x00) > + return; > + > + /* > + * On these buggy HW, PCIe capability structure is expected to be at > + * 0xac and should terminate the list > + * > + * Borrow the similar logic from theIntel DH895xCC VFs fixup to save > + * the PCIe capability list > + */ > + pos = 0xac; > + pci_read_config_word(pdev, pos, ®16); > + if (reg16 == (0x0000 | PCI_CAP_ID_EXP)) { > + u32 status; > + > +#ifndef PCI_EXP_SAVE_REGS > +#define PCI_EXP_SAVE_REGS 7 > +#endif > + int size = PCI_EXP_SAVE_REGS * sizeof(u16); > + > + pdev->pcie_cap = pos; > + pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); > + pdev->pcie_flags_reg = reg16; > + pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, ®16); > + pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD; Is there any way you can fix this in iproc_pcie_config_read() instead, by making it notice when we're reading a corrupted part of config space, and then returning the correct data instead? Is it just the next capability pointer that's corrupted? If you could fix it in the config accessor, lspci would automatically show all the correct data (I think lspci will still show the wrong data with this patch). The quirk seems like a maintenance issue because anything that calls pci_find_capability(pdev, PCI_CAP_ID_EXP) will get the wrong answer. > + > + pdev->cfg_size = PCI_CFG_SPACE_EXP_SIZE; > + if (pci_read_config_dword(pdev, PCI_CFG_SPACE_SIZE, &status) != > + PCIBIOS_SUCCESSFUL || (status == 0xffffffff)) > + pdev->cfg_size = PCI_CFG_SPACE_SIZE; > + > + if (pci_find_saved_cap(pdev, PCI_CAP_ID_EXP)) > + return; > + > + state = kzalloc(sizeof(*state) + size, GFP_KERNEL); > + if (!state) > + return; > + > + state->cap.cap_nr = PCI_CAP_ID_EXP; > + state->cap.cap_extended = 0; > + state->cap.size = size; > + cap = (u16 *)&state->cap.data[0]; > + pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &cap[i++]); > + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &cap[i++]); > + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &cap[i++]); > + pcie_capability_read_word(pdev, PCI_EXP_RTCTL, &cap[i++]); > + pcie_capability_read_word(pdev, PCI_EXP_DEVCTL2, &cap[i++]); > + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL2, &cap[i++]); > + pcie_capability_read_word(pdev, PCI_EXP_SLTCTL2, &cap[i++]); > + hlist_add_head(&state->next, &pdev->saved_cap_space); > + } > +} > +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_57810, > + quirk_paxc_pcie_capability); > +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16cd, > + quirk_paxc_pcie_capability); > +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x16f0, > + quirk_paxc_pcie_capability); > +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd802, > + quirk_paxc_pcie_capability); > +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0xd804, > + quirk_paxc_pcie_capability); > #endif > > /* Originally in EDAC sources for i82875P: > -- > 2.1.4 >