From patchwork Tue Aug 1 13:00:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver O'Halloran X-Patchwork-Id: 796217 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xMGg85yZvz9sR8 for ; Tue, 1 Aug 2017 23:01:56 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jVsfPndj"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xMGg84KgCzDsQd for ; Tue, 1 Aug 2017 23:01:56 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jVsfPndj"; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mail-pf0-x244.google.com (mail-pf0-x244.google.com [IPv6:2607:f8b0:400e:c00::244]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3xMGdd6VMzzDsQ3 for ; Tue, 1 Aug 2017 23:00:37 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jVsfPndj"; dkim-atps=neutral Received: by mail-pf0-x244.google.com with SMTP id t83so2410741pfj.3 for ; Tue, 01 Aug 2017 06:00:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=l+2LO0X72dXCiDL6MFTl9U2lao7J/cXFKR+LlwQ7mEg=; b=jVsfPndjitXjcN8xoiFUqbFshs2HIVaxsKxx/hSgdRQ1YDygviuf59K+vfKeBU4oWE 0nP/ovQdqJU02ys32sr/GgPzkxWLDY9Wu8xaZIzjBQnc203jgS4IrjEuyi8BvF8kFmwj 1LjmsLqCzRXdm+p+t8cFw6pIYlnROHSzgCSqDOmKnqN+0x4EPD6BgDMULUY0Rx9Rnm6f tjybIroLSO3vkCoUx07btohNuh8qHp3TlMbaYkpi6XGig/7DbdZiHe5IuAgQmuZES0cE dmwiF5951KjW7vkDq4FP6e+Btvw0Q6lgjLk9qDEnbsxXk/MiKXMjJfsfwjSXTxhdIttU o3Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=l+2LO0X72dXCiDL6MFTl9U2lao7J/cXFKR+LlwQ7mEg=; b=ZhkM9p8ZDqatUze156vK9XctNkIZ486mCQ18JdkRZTYgims/nJ6DGkndSJwdXQHLiY 222hBfbrvh7Z1PAsxlzOQ2KEsZkz0bVDF1n0td9IubMdAS14zxcvNBOBqQ8lvznjaZQu N8qtwiOZEw0eoCBAGuTFSbiI9m4nvROZz3x0/Bj0zqwsHn8sQpnHZYdhfGymN3hfZAOc DR7imX5IQ7EB/U77OnQcDZiE+KeyMCsYxHcKhDGST6xsIBoroaLnOtDZaGVRiAeaY3i7 39ewNLQ2YyFaQ92pDoMpaZHXQ/ghOHkGlg3q3B/tRmSRAh3tj34gSV1Guh6zYIltY1xk ZrpA== X-Gm-Message-State: AIVw110peSDht/VuDHolAtjhTqUFXGKs1Zcz1AoGQaWHbRN2OBSUdyJa WE2SghWduAXI34B+ X-Received: by 10.84.164.225 with SMTP id l30mr20749477plg.317.1501592435672; Tue, 01 Aug 2017 06:00:35 -0700 (PDT) Received: from flat-canetoad.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id g22sm3235806pgn.65.2017.08.01.06.00.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 01 Aug 2017 06:00:35 -0700 (PDT) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Tue, 1 Aug 2017 23:00:00 +1000 Message-Id: <20170801130007.8990-6-oohall@gmail.com> X-Mailer: git-send-email 2.9.4 In-Reply-To: <20170801130007.8990-1-oohall@gmail.com> References: <20170801130007.8990-1-oohall@gmail.com> Subject: [Skiboot] [RFC 05/12] core/pci-dt-slot: Represent PCIe slots in the devicetree X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" In P9 we get information about the physical PCIe slot topology through the HDAT. As a rule we never directly consume the HDAT inside of Skiboot and we always parse and incorporate the data from HDAT into the Skiboot device tree. Signed-off-by: Oliver O'Halloran --- core/Makefile.inc | 2 +- core/pci-dt-slot.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/pci-slot.h | 7 ++ 3 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 core/pci-dt-slot.c diff --git a/core/Makefile.inc b/core/Makefile.inc index c343386cf995..619ab398065d 100644 --- a/core/Makefile.inc +++ b/core/Makefile.inc @@ -9,7 +9,7 @@ CORE_OBJS += vpd.o hostservices.o platform.o nvram.o nvram-format.o hmi.o CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o -CORE_OBJS += vas.o +CORE_OBJS += vas.o pci-dt-slot.o ifeq ($(SKIBOOT_GCOV),1) CORE_OBJS += gcov-profiling.o diff --git a/core/pci-dt-slot.c b/core/pci-dt-slot.c new file mode 100644 index 000000000000..e394d76c0b4a --- /dev/null +++ b/core/pci-dt-slot.c @@ -0,0 +1,211 @@ +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#undef pr_fmt +#define pr_fmt(fmt) "DT-SLOT: " fmt + +#define PCIDBG(_p, _bdfn, fmt, a...) \ + prlog(PR_DEBUG, "PHB#%04x:%02x:%02x.%x " fmt, \ + (_p)->opal_id, \ + ((_bdfn) >> 8) & 0xff, \ + ((_bdfn) >> 3) & 0x1f, (_bdfn) & 0x7, ## a) + +struct dt_node *dt_slots; + +static struct dt_node *map_phb_to_slot(struct phb *phb) +{ + uint32_t chip_id = dt_get_chip_id(phb->dt_node); + uint32_t phb_idx = dt_prop_get_u32_def(phb->dt_node, + "ibm,phb-index", 0); + struct dt_node *slot_node; + + dt_for_each_child(dt_slots, slot_node) { + u32 reg[2]; + + if (!dt_has_node_property(slot_node, "compatible", + "ibm,pcie-root-port")) + continue; + + reg[0] = dt_prop_get_cell(slot_node, "reg", 0); + reg[1] = dt_prop_get_cell(slot_node, "reg", 1); + + if (reg[0] == chip_id && reg[1] == phb_idx) + return slot_node; + } + + return NULL; +} + +static struct dt_node *map_downport_to_slot(struct phb *phb, + struct pci_device *pd) +{ + struct dt_node *bus_node, *child; + struct pci_device *cursor; + uint32_t port_dev_id; + + /* + * Downports are a little bit special since we need to figure + * out which PCI device corresponds to which down port in the + * slot map. + * + * XXX: I'm assuming the ordering of port IDs and probed + * PCIe switch downstream devices is the same. We should + * check what we actually get in the HDAT. + */ + + list_for_each(&pd->parent->children, cursor, link) + if (cursor == pd) + break; + + /* the child should always be on the parent's child list */ + assert(cursor); + port_dev_id = (cursor->bdfn & 0xff) >> 3; + + bus_node = map_pci_dev_to_slot(phb, pd->parent); + if (bus_node) { + dt_for_each_child(bus_node, child) + if (dt_prop_get_u32(child, "reg") == port_dev_id) + return child; + } + + /* unused downport */ + return NULL; +} + +static struct dt_node *__map_pci_dev_to_slot(struct phb *phb, + struct pci_device *pd) +{ + struct dt_node *child, *bus_node, *wildcard= NULL; + + if (!pd || !pd->parent || pd->dev_type == PCIE_TYPE_ROOT_PORT) + return map_phb_to_slot(phb); + + if (pd->dev_type == PCIE_TYPE_SWITCH_DNPORT) + return map_downport_to_slot(phb, pd); + + /* + * For matching against devices always use the 0th function. + * This is necessary since some functions may have a different + * VDID to the base device. e.g. The DMA engines in PLX switches + */ + if (pd->bdfn & 0x7) { + struct pci_device *cursor; + + PCIDBG(phb, pd->bdfn, "mapping fn %x to 0th fn (%x)\n", + pd->bdfn, pd->bdfn & (~0x7)); + + list_for_each(&pd->parent->children, cursor, link) + if ((pd->bdfn & ~0x7) == cursor->bdfn) + return map_pci_dev_to_slot(phb, cursor); + + return NULL; + } + + /* No slot information for this device. Might be a firmware bug */ + bus_node = map_pci_dev_to_slot(phb, pd->parent); + if (!bus_node) + return NULL; + + /* + * If this PCI device is mounted on a card the parent "bus" + * may actually be a slot or builtin. + */ + if (list_empty(&bus_node->children)) + return bus_node; + + /* find the device in the parent bus node */ + dt_for_each_child(bus_node, child) { + u32 vdid; + + /* "pluggable" and "builtin" without unit addrs are wildcards */ + if (!dt_has_node_property(child, "reg", NULL)) { + if (wildcard) { + prerror("Duplicate wildcard entry! Already have %s, found %s", + wildcard->name, child->name); + assert(0); + } + + wildcard = child; + continue; + } + + /* NB: the pci_device vdid is did,vid rather than vid,did */ + vdid = dt_prop_get_cell(child, "reg", 1) << 16 | + dt_prop_get_cell(child, "reg", 0); + + if (vdid == pd->vdid) + return child; + } + + if (!wildcard) + PCIDBG(phb, pd->bdfn, + "Unable to find a slot for device %.4x:%.4x\n", + (pd->vdid & 0xffff0000) >> 16, pd->vdid & 0xffff); + + return wildcard; +} + +struct dt_node *map_pci_dev_to_slot(struct phb *phb, struct pci_device *pd) +{ + uint32_t bdfn = pd ? pd->bdfn : 0; + struct dt_node *n; + char *path; + + if (pd && pd->slot && pd->slot->data) + return pd->slot->data; + + PCIDBG(phb, bdfn, "Finding slot\n"); + + n = __map_pci_dev_to_slot(phb, pd); + if (!n) { + PCIDBG(phb, bdfn, "No slot found!\n"); + } else { + path = dt_get_path(n); + PCIDBG(phb, bdfn, "Slot found %s\n", path); + free(path); + } + + return n; +} + +int __print_slot(struct phb *phb, struct pci_device *pd, void *userdata); +int __print_slot(struct phb *phb, struct pci_device *pd, + void __unused *userdata) +{ + struct dt_node *node; + struct dt_node *pnode; + char *c = NULL; + u32 phandle = 0; + + if (!pd) + return 0; + + node = map_pci_dev_to_slot(phb, pd); + + /* at this point all node associations should be done */ + if (pd->dn && dt_has_node_property(pd->dn, "ibm,pcie-slot", NULL)) { + phandle = dt_prop_get_u32(pd->dn, "ibm,pcie-slot"); + pnode = dt_find_by_phandle(dt_root, phandle); + + assert(node == pnode); + } + + if (node) + c = dt_get_path(node); + + PCIDBG(phb, pd->bdfn, "Mapped to slot %s (%x)\n", + c ? c : "", phandle); + + free(c); + + return 0; +} diff --git a/include/pci-slot.h b/include/pci-slot.h index 5cc54f837155..c86a21d7f1a0 100644 --- a/include/pci-slot.h +++ b/include/pci-slot.h @@ -256,4 +256,11 @@ extern struct pci_slot *pcie_slot_create(struct phb *phb, extern void pci_slot_add_dt_properties(struct pci_slot *slot, struct dt_node *np); extern struct pci_slot *pci_slot_find(uint64_t id); + +/* DT based slot map */ + +extern struct dt_node *dt_slots; +extern struct dt_node *map_pci_dev_to_slot(struct phb *phb, + struct pci_device *pd); + #endif /* __PCI_SLOT_H */