From patchwork Wed Jan 12 15:18:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Pali_Roh=C3=A1r?= X-Patchwork-Id: 12711517 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7F4A3C433EF for ; Wed, 12 Jan 2022 15:21:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=/pFt6SSDtAMiSyBN6PMzjSG3ptygc0WR4nwvgKrQPqI=; b=ApUu2jKgkrmHzO UwhQZQcFRiwSvMkPT/fgMpaEY4uuaUwqp6kf1EJiBIRpYH+3sgvIGKYQS75O3cX2ya3WHy1BSjUmA 0meP2iJHX+Trrbv0b5K6IqsMZNL5cEVnmFms+yJPLjTNVLTIjZg3JE8N2mP2tQCCNnDLXPYxdxByx I0N7emhE9hbwy8DGe11bK1YaI1d+kLIk8qr0atxzaXR+y6+xXLGNOaeXspZXmwtFMj3DqkxkulcEp Go0bk/JAgGb6TpLAa1G8QxDDodcQgEK54YEckU0zRJgt3itIFe/VXSxjHpyVrTb2epTV10hydpjiy Pjz847wSM0N0A4uPV6rA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1n7fPs-002r3o-AW; Wed, 12 Jan 2022 15:20:00 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1n7fOW-002qVV-PB for linux-arm-kernel@lists.infradead.org; Wed, 12 Jan 2022 15:18:41 +0000 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 218A661913; Wed, 12 Jan 2022 15:18:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A7E6C36AEA; Wed, 12 Jan 2022 15:18:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1642000716; bh=YzSw0jzAbp3IOps2JabCEF2fRcUsifDh7TuQoPY2nDI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EdLceE6/HmquP+9HVKmrBDgoPvGPncj7SewfyVMlpL78YedkvGF9tJQ7nXdlqrEr9 AN29VF4YlhWTLCnMkGCL8gKAjYGoU1RKcRnnUQwJDnZ5TrkUCOTmiHcpRy3GNqYjCi wU/7ABf0lmnaVBAZMMR0JK2TgmlhFlZUKwGR0R/Z8SYbwnJgSAhxXLGBjH7sqi8QSv DmXUBrASqYV5pAoGtvTHJSSeR/5+dZSqbDxoTGpMjTRLDR6QTo1ulcntPEeC+LoVQq rJph0a8/tSGCcUBcU7np7VibW0dEnhj1uD6xXMLN5BDKig0NaxjaLOZjOEvOi06GTI PbWPwGTGGadnQ== Received: by pali.im (Postfix) id 6527422CA; Wed, 12 Jan 2022 16:18:33 +0100 (CET) From: =?utf-8?q?Pali_Roh=C3=A1r?= To: Lorenzo Pieralisi , Bjorn Helgaas , Rob Herring , Thomas Petazzoni , =?utf-8?q?Krzysztof_Wilczy?= =?utf-8?q?=C5=84ski?= , =?utf-8?q?Marek_Beh=C3=BAn?= , Russell King Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 02/11] PCI: pci-bridge-emul: Add support for PCIe extended capabilities Date: Wed, 12 Jan 2022 16:18:05 +0100 Message-Id: <20220112151814.24361-3-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20220112151814.24361-1-pali@kernel.org> References: <20220105150239.9628-1-pali@kernel.org> <20220112151814.24361-1-pali@kernel.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220112_071836_958520_9BD6D288 X-CRM114-Status: GOOD ( 22.62 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Russell King Add support for PCIe extended capabilities, which we just redirect to the emulating driver. Signed-off-by: Russell King [pali: Fix writing new value with W1C bits] Signed-off-by: Pali Rohár --- drivers/pci/pci-bridge-emul.c | 77 +++++++++++++++++++++++------------ drivers/pci/pci-bridge-emul.h | 15 +++++++ 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 56b2cb741498..9f4f173f0650 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -433,10 +433,16 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where, read_op = bridge->ops->read_pcie; cfgspace = (__le32 *) &bridge->pcie_conf; behavior = bridge->pcie_cap_regs_behavior; - } else { - /* Beyond our PCIe space */ + } else if (reg < PCI_CFG_SPACE_SIZE) { + /* Rest of PCI space not implemented */ *value = 0; return PCIBIOS_SUCCESSFUL; + } else { + /* PCIe extended capability space */ + reg -= PCI_CFG_SPACE_SIZE; + read_op = bridge->ops->read_ext; + cfgspace = NULL; + behavior = NULL; } if (read_op) @@ -444,15 +450,20 @@ int pci_bridge_emul_conf_read(struct pci_bridge_emul *bridge, int where, else ret = PCI_BRIDGE_EMUL_NOT_HANDLED; - if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) - *value = le32_to_cpu(cfgspace[reg / 4]); + if (ret == PCI_BRIDGE_EMUL_NOT_HANDLED) { + if (cfgspace) + *value = le32_to_cpu(cfgspace[reg / 4]); + else + *value = 0; + } /* * Make sure we never return any reserved bit with a value * different from 0. */ - *value &= behavior[reg / 4].ro | behavior[reg / 4].rw | - behavior[reg / 4].w1c; + if (behavior) + *value &= behavior[reg / 4].ro | behavior[reg / 4].rw | + behavior[reg / 4].w1c; if (size == 1) *value = (*value >> (8 * (where & 3))) & 0xff; @@ -498,8 +509,15 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, write_op = bridge->ops->write_pcie; cfgspace = (__le32 *) &bridge->pcie_conf; behavior = bridge->pcie_cap_regs_behavior; - } else { + } else if (reg < PCI_CFG_SPACE_SIZE) { + /* Rest of PCI space not implemented */ return PCIBIOS_SUCCESSFUL; + } else { + /* PCIe extended capability space */ + reg -= PCI_CFG_SPACE_SIZE; + write_op = bridge->ops->write_ext; + cfgspace = NULL; + behavior = NULL; } shift = (where & 0x3) * 8; @@ -513,29 +531,38 @@ int pci_bridge_emul_conf_write(struct pci_bridge_emul *bridge, int where, else return PCIBIOS_BAD_REGISTER_NUMBER; - /* Keep all bits, except the RW bits */ - new = old & (~mask | ~behavior[reg / 4].rw); + if (behavior) { + /* Keep all bits, except the RW bits */ + new = old & (~mask | ~behavior[reg / 4].rw); - /* Update the value of the RW bits */ - new |= (value << shift) & (behavior[reg / 4].rw & mask); + /* Update the value of the RW bits */ + new |= (value << shift) & (behavior[reg / 4].rw & mask); - /* Clear the W1C bits */ - new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); + /* Clear the W1C bits */ + new &= ~((value << shift) & (behavior[reg / 4].w1c & mask)); + } else { + new = old & ~mask; + new |= (value << shift) & mask; + } - /* Save the new value with the cleared W1C bits into the cfgspace */ - cfgspace[reg / 4] = cpu_to_le32(new); + if (cfgspace) { + /* Save the new value with the cleared W1C bits into the cfgspace */ + cfgspace[reg / 4] = cpu_to_le32(new); + } - /* - * Clear the W1C bits not specified by the write mask, so that the - * write_op() does not clear them. - */ - new &= ~(behavior[reg / 4].w1c & ~mask); + if (behavior) { + /* + * Clear the W1C bits not specified by the write mask, so that the + * write_op() does not clear them. + */ + new &= ~(behavior[reg / 4].w1c & ~mask); - /* - * Set the W1C bits specified by the write mask, so that write_op() - * knows about that they are to be cleared. - */ - new |= (value << shift) & (behavior[reg / 4].w1c & mask); + /* + * Set the W1C bits specified by the write mask, so that write_op() + * knows about that they are to be cleared. + */ + new |= (value << shift) & (behavior[reg / 4].w1c & mask); + } if (write_op) write_op(bridge, reg, old, new, mask); diff --git a/drivers/pci/pci-bridge-emul.h b/drivers/pci/pci-bridge-emul.h index 4953274cac18..6b5f75b2ad02 100644 --- a/drivers/pci/pci-bridge-emul.h +++ b/drivers/pci/pci-bridge-emul.h @@ -90,6 +90,14 @@ struct pci_bridge_emul_ops { */ pci_bridge_emul_read_status_t (*read_pcie)(struct pci_bridge_emul *bridge, int reg, u32 *value); + + /* + * Same as ->read_base(), except it is for reading from the + * PCIe extended capability configuration space. + */ + pci_bridge_emul_read_status_t (*read_ext)(struct pci_bridge_emul *bridge, + int reg, u32 *value); + /* * Called when writing to the regular PCI bridge configuration * space. old is the current value, new is the new value being @@ -105,6 +113,13 @@ struct pci_bridge_emul_ops { */ void (*write_pcie)(struct pci_bridge_emul *bridge, int reg, u32 old, u32 new, u32 mask); + + /* + * Same as ->write_base(), except it is for writing from the + * PCIe extended capability configuration space. + */ + void (*write_ext)(struct pci_bridge_emul *bridge, int reg, + u32 old, u32 new, u32 mask); }; struct pci_bridge_reg_behavior;