Received: by 2002:a05:6a10:a852:0:0:0:0 with SMTP id d18csp1473299pxy; Thu, 6 May 2021 08:39:22 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxlQJx/r98ElQpUorhldfMcz5ria9le6bmie3i/SX/rL9w8pJ6t/je9zrcLKKQdr5NFK8o4 X-Received: by 2002:a17:902:8307:b029:ec:86a4:90fa with SMTP id bd7-20020a1709028307b02900ec86a490famr5238590plb.22.1620315561876; Thu, 06 May 2021 08:39:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620315561; cv=none; d=google.com; s=arc-20160816; b=X+Kj530q89JbfGR8PgqJt3ytrMNfPx2h77g+zKllzQmsr0E+vMMyypGmJ1VNAd6bFY itAe9FpBNJ5SIFxmKbkE1yNJMBgLJXSKKYU9leC5f44Re+vRZx/nvO8JY75M8mG57mI1 5HMXwiy3QAMIKpLUx4a1Vw+Ay52oo+Na94O/KJT7rZsRzDiYwlm/lLrgsp/4rMpk+qr+ A12DxYnVSCWdKClUE60hNW87dPDQAgHWbPh+F9xWErx1PaMEpsBvyfGiRg05xEXIRUTs cr/xZ7op3dVa2T1hi/V/mxU4tNEsJxYwLfhKjM/6qcOyhthjfj3W/lX/tvMpPowl7V/l veeA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=rVsyvk/wDz+Qse+xC55/mo9JAyVxLTxGMY+/XCFso9c=; b=J0dwlgF0va1NT2ICp43LV8VAfbwesJ9deOi5ceProK8kP28yNhxrZAVyGkTqVKJfhy qD69oXoGjEgARZFEjtRtJpVueowbj3A3F6phjfX2vznVBdOGVpHjKCY+g6kfv2DagzpV ZZEu0rffzI8ezANkAXEOFO1jfHvtWt07flpODhmKmSIkzlh/8cHXsMf21o89ILok0z9V Yjmt6har63WypIYexK0ui1adgmJj3/dyuklLHL6TVphUcvQCMJ3P0t64daCuDDI2yS6a I8TiFl7y+TEtxP9TJwWsAxravk4X8cjskaolu02mhQ7k8ndABoSOfyGbSloOx6sfLH5X ro6w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Dh1vhcJJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 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. [23.128.96.18]) by mx.google.com with ESMTP id j1si3420906pfr.175.2021.05.06.08.39.09; Thu, 06 May 2021 08:39:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=Dh1vhcJJ; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 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 S236108AbhEFPiB (ORCPT + 99 others); Thu, 6 May 2021 11:38:01 -0400 Received: from mail.kernel.org ([198.145.29.99]:46132 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235768AbhEFPeB (ORCPT ); Thu, 6 May 2021 11:34:01 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 35EFD61919; Thu, 6 May 2021 15:32:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1620315176; bh=hjo0BAh8/TrXrQZkushaXu4N5LMhaWkVsVmV1/6ftDk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Dh1vhcJJYtbozzm9tYZuMVr3xW2todeA5yDuns656iomD3BgScMh9g4Cp5PbUmw38 7jbsRgj7iDlnpJ75OQ43qkrEbI7VgBraSEINnbkvhN3orBjYsjqhLStfl7yt4g3tXT 9zP6un2sviaI6VU/eWUEqoL2WC0nF8dlVgjEyc1eWrEdhCbPMqw9wfq/0yrJjm1zWJ mMZ2ytRlFECFuKySVamBgQdcWQ7L0e6XtMrXlRu0X8Gk7DJ4OTNheqAZ6513100vJR EksPYnhdly9pOg5a2g+WXCNguErI7b4nUKbyqEmwIAkRQGKMrb8YuiSBDaTAKs72s8 P7DIwL0F9ulvA== Received: by pali.im (Postfix) id E16FF89A; Thu, 6 May 2021 17:32:55 +0200 (CEST) From: =?UTF-8?q?Pali=20Roh=C3=A1r?= To: Lorenzo Pieralisi , Thomas Petazzoni , Rob Herring , Bjorn Helgaas Cc: Russell King , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Remi Pommarel , Xogium , Tomasz Maciej Nowak , Marc Zyngier , linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH 41/42] PCI: pci-bridge-emul: add support for PCIe extended capabilities Date: Thu, 6 May 2021 17:31:52 +0200 Message-Id: <20210506153153.30454-42-pali@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210506153153.30454-1-pali@kernel.org> References: <20210506153153.30454-1-pali@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Russell King Add support for PCIe extended capabilities, which we just redirect to the emulating driver. Signed-off-by: Russell King --- drivers/pci/pci-bridge-emul.c | 52 +++++++++++++++++++++++++---------- drivers/pci/pci-bridge-emul.h | 15 ++++++++++ 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/drivers/pci/pci-bridge-emul.c b/drivers/pci/pci-bridge-emul.c index 63959e4b188a..236036fdeaa2 100644 --- a/drivers/pci/pci-bridge-emul.c +++ b/drivers/pci/pci-bridge-emul.c @@ -385,10 +385,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) @@ -396,15 +402,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; @@ -450,8 +461,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; @@ -465,16 +483,22 @@ 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; + } - cfgspace[reg / 4] = cpu_to_le32(new); + if (cfgspace) + cfgspace[reg / 4] = cpu_to_le32(new); 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 49bbd37ee318..2552ab660b08 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; -- 2.20.1