From patchwork Fri Apr 20 04:40:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver O'Halloran X-Patchwork-Id: 901631 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40S38S0qhrz9s1w for ; Fri, 20 Apr 2018 14:41:12 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kACMQMA8"; 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 40S38R6PP0zF24D for ; Fri, 20 Apr 2018 14:41:11 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com 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="kACMQMA8"; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:400e:c00::243; helo=mail-pf0-x243.google.com; envelope-from=oohall@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="kACMQMA8"; dkim-atps=neutral Received: from mail-pf0-x243.google.com (mail-pf0-x243.google.com [IPv6:2607:f8b0:400e:c00::243]) (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 40S3893ZvRzF22Z for ; Fri, 20 Apr 2018 14:40:57 +1000 (AEST) Received: by mail-pf0-x243.google.com with SMTP id o16so3687045pfk.9 for ; Thu, 19 Apr 2018 21:40:56 -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; bh=ECI5d8yynbw0ykjIxRjLVIK0buT7CBIP5lsUPcMdV9k=; b=kACMQMA8LiX1UaoiR6ulluIjmelRWznQVdMY7HF+ZM6cFBZRIW5dhOCqRtWWekuYxn lyPtGcA3ffZektv/CeZYIQeLgC+qmglshAjVAyhjLHsRhkz/D11+Cz3cfc6LXcjJOszu w2dB2O9jCvvSWagzhhtEpT4Aut1/pZwmCnCCgPk9A4navyE8LZIgz3Ih47MxGuJSsUqF 696+C67Zrdwxn7UXO4raBzN1Fbw9gNhLv895+QD2tGkqErpUlo3BF9E4PxM9UZq0g0Cg s/wyq10HpHN8xv2pSsu/jgjPV556w76syCR+ea+yAsGsQxvLelxKmylG+/ApSINfAFH1 BF7w== 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; bh=ECI5d8yynbw0ykjIxRjLVIK0buT7CBIP5lsUPcMdV9k=; b=bktlOASQfIoYIgrfPnlEgHOxr3FMKVfRd0f4iJo1ZOFiGYX9RGJpOete2j3wSR3wwK tih1+J2i4GE8lLnBEXp1brxjqkVL4eGsJZT4W7g+5Hp/4R/SJBFurFjxhiqZtA1nsgWZ w4wfApHRwG+R31WCiUFvRBbPW00VJEke1S7t7Cgt/p8t31Kd9Jlec9sNH9RY0pnqr13A F0EShK7BBXQy8rdJz4HB8IJfzyJVNI11fGAqdTsL3oXn9sW3BoJ5fyvLWAzed2bksyjD JoLj4dghsjcuu29198Uwt4wja6d9FZJcI366mXvjAY11tRhs9nfVvqLPjvYLQQkEuhEk NZdA== X-Gm-Message-State: ALQs6tD9md1xL5KmNe/lWoyAe1ym2/ilpIEUiwzyBOH7LHU0S83A08Mk rPSpM0GlxrSroYMkJrYG2WmoFg== X-Google-Smtp-Source: AIpwx49Csu0eFYxZ9+s0YZ29iXR826fexf47iz3vV4G3j/66TGwj/vtpLbdyPEyBQJ5Og2K7+3hR5g== X-Received: by 10.99.135.198 with SMTP id i189mr7147218pge.2.1524199254961; Thu, 19 Apr 2018 21:40:54 -0700 (PDT) Received: from flat-canetoad.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id v1sm9728632pfg.144.2018.04.19.21.40.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 19 Apr 2018 21:40:54 -0700 (PDT) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Fri, 20 Apr 2018 14:40:39 +1000 Message-Id: <20180420044041.29817-1-oohall@gmail.com> X-Mailer: git-send-email 2.9.5 Subject: [Skiboot] [PATCH 1/3] pci-dt-slot: Big ol' cleanup X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.26 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" The underlying data that we get from HDAT can only really describe a PCIe system. As such we can simplify the devicetree slot lookup code by only caring about the important cases, namly, root ports and switch downstream ports. This also fixes a bug where root port didn't get a Slot label applied which results in devices under that port not having ibm,loc-code set. This results in the EEH core being unable to report the location of EEHed devices under that port. Signed-off-by: Oliver O'Halloran --- core/pci-dt-slot.c | 154 +++++++++++++++++++++++++---------------------------- 1 file changed, 74 insertions(+), 80 deletions(-) diff --git a/core/pci-dt-slot.c b/core/pci-dt-slot.c index bee7ba47c445..4f5a0805e005 100644 --- a/core/pci-dt-slot.c +++ b/core/pci-dt-slot.c @@ -66,95 +66,33 @@ static struct dt_node *map_phb_to_slot(struct phb *phb) return NULL; } -static struct dt_node *map_downport_to_slot(struct phb *phb, - struct pci_device *pd) +static struct dt_node *find_devfn(struct dt_node *bus, uint32_t bdfn) { - struct dt_node *bus_node, *child; - struct pci_device *cursor; - uint32_t port_dev_id; + uint32_t port_dev_id = (bdfn >> 3) & 0x1f; + struct dt_node *child; - /* - * 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 >> 3) & 0x1f; - - bus_node = map_pci_dev_to_slot(phb, pd->parent); - if (!bus_node) - return NULL; - - dt_for_each_child(bus_node, child) - if (dt_prop_get_u32(child, "reg") == port_dev_id) + dt_for_each_child(bus, child) + if (dt_prop_get_u32_def(child, "reg", ~0u) == port_dev_id) return child; - /* unused downport */ return NULL; } -static struct dt_node *__map_pci_dev_to_slot(struct phb *phb, +/* Looks for a device device under this slot. */ +static struct dt_node *find_dev_under_slot(struct dt_node *slot, 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; + struct dt_node *child, *wildcard = NULL; /* find the device in the parent bus node */ - dt_for_each_child(bus_node, child) { + dt_for_each_child(slot, child) { u32 vdid; /* "pluggable" and "builtin" without unit addrs are wildcards */ if (!dt_has_node_property(child, "reg", NULL)) { - if (wildcard) { + if (wildcard) prerror("Duplicate wildcard entry! Already have %s, found %s", wildcard->name, child->name); - assert(0); - } wildcard = child; continue; @@ -169,30 +107,86 @@ static struct dt_node *__map_pci_dev_to_slot(struct phb *phb, } if (!wildcard) - PCIDBG(phb, pd->bdfn, + PCIDBG(pd->phb, pd->bdfn, "Unable to find a slot for device %.4x:%.4x\n", (pd->vdid & 0xffff0000) >> 16, pd->vdid & 0xffff); return wildcard; } +/* + * If the `pd` is a bridge this returns a node with a compatible of + * ibm,pcie-port to indicate it's a "slot node". + */ +static struct dt_node *find_node_for_dev(struct phb *phb, + struct pci_device *pd) +{ + struct dt_node *sw_slot, *sw_up; + + assert(pd); + + if (pd->slot && pd->slot->data) + return pd->slot->data; + + /* + * Example DT: + * /root-complex@8,5/switch-up@10b5,8725/down-port@4 + */ + switch (pd->dev_type) { + case PCIE_TYPE_ROOT_PORT: // find the root-complex@, node + return map_phb_to_slot(phb); + + case PCIE_TYPE_SWITCH_DNPORT: // grab the down-port@ + /* + * Walk up the topology to find the slot that contains + * the switch upstream port is connected to. In the example + * this would be the root-complex@8,5 node. + */ + sw_slot = find_node_for_dev(phb, pd->parent->parent); + if (!sw_slot) + return NULL; + + /* find the per-device node for this switch */ + sw_up = find_dev_under_slot(sw_slot, pd->parent); + if (!sw_up) + return NULL; + + /* find this down port */ + return find_devfn(sw_up, pd->bdfn & 0x1f); + + default: + PCIDBG(phb, pd->bdfn, + "Trying to find a slot for non-pcie bridge type %d\n", + pd->dev_type); + assert(0); + } + + return NULL; +} + 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; + assert(pd); + + /* + * Having a slot only makes sense for root and switch downstream ports. + * We don't care about PCI-X. + */ + if (pd->dev_type != PCIE_TYPE_SWITCH_DNPORT && + pd->dev_type != PCIE_TYPE_ROOT_PORT) + return NULL; - PCIDBG(phb, bdfn, "Finding slot\n"); + PCIDBG(phb, pd->bdfn, "Finding slot\n"); - n = __map_pci_dev_to_slot(phb, pd); + n = find_node_for_dev(phb, pd); if (!n) { - PCIDBG(phb, bdfn, "No slot found!\n"); + PCIDBG(phb, pd->bdfn, "No slot found!\n"); } else { path = dt_get_path(n); - PCIDBG(phb, bdfn, "Slot found %s\n", path); + PCIDBG(phb, pd->bdfn, "Slot found %s\n", path); free(path); }