From patchwork Tue Aug 22 08:15:41 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: 804331 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 3xc3kW4Qwfz9sNd for ; Tue, 22 Aug 2017 18:34:11 +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="jZ8ymb9Q"; 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 3xc3kW3FvVzDr34 for ; Tue, 22 Aug 2017 18:34:11 +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="jZ8ymb9Q"; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mail-pf0-x241.google.com (mail-pf0-x241.google.com [IPv6:2607:f8b0:400e:c00::241]) (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 3xc3KW0bYkzDqh9 for ; Tue, 22 Aug 2017 18:15:59 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="jZ8ymb9Q"; dkim-atps=neutral Received: by mail-pf0-x241.google.com with SMTP id h75so5267353pfh.5 for ; Tue, 22 Aug 2017 01:15:58 -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=LmF6yYzoWi03Z9ZpG8YQ5nzqYxl6XR1uibBWowyZg/c=; b=jZ8ymb9QPa0zhfnzrVqeFYXIGgVt0077xtWSSUahR1cnasueaicUm+m5//ds7rfCyi Q/fcin2d4T3c5/8WVEKcLJCOThLotwkB2KCiYeDo+VWdS7G3aPsQpD44pKmQIlexp4W+ hXl+W290w3Ve58pBxuXlAYeCiBqeW5PAbNuJZvVshYj79mRiuaE8Hbd3rikPoXIq2Dp9 gSxkyYGIRpQptJIV+kfFpiCb9e/RKQJBZXnguO1Bzvvt8gwNfyw2/22yylc4mTiHwM4Z KgCqNTdvn7NSxAV6e0aBL38uV/U0MmO27EhCDfNYCTzNQ/uytp+FFqmx51G8pTmJP8OZ JMuQ== 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=LmF6yYzoWi03Z9ZpG8YQ5nzqYxl6XR1uibBWowyZg/c=; b=b854klw98EN5B2ULSNORHg0CuJzLOo1z0OBwUa0sztZinEUDybJFYn1Y3ebUmp5ufO ExCV2ZvFuNP3c2fWkXzF8x7ln7IFdBSYRrYv0ugYlaKvV+tpNxG/o0AAaDvSEnyY4Mh4 0ItIRNQcxKJx9c/pL5ucfdjqmxNjGHzcjdorI0UevtbkAxyeNbvfuW03PUAgtRigCS4z O533LRcsVdN/K0fhRfHuD5mJSK3l2RfD5qKH0CGvpMAcUKDNG1+Lu0JzycBzzyptTNE2 iZuX6gEeJ8T22OEfKerAIqqqqEsCUi9GoQ5zPOc6BAa4nudBuBubve3eseMYVqk1veLM FRlQ== X-Gm-Message-State: AHYfb5iQWnyf2UR6lNcxH8PNT4Pjwhv8s7nx83YQaPD1BXRIhHT9EK+M H4gsK092k9Uw6w2w X-Received: by 10.101.87.205 with SMTP id q13mr19310887pgr.249.1503389756929; Tue, 22 Aug 2017 01:15:56 -0700 (PDT) Received: from flat-canetoad.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id a22sm24074476pfj.94.2017.08.22.01.15.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Aug 2017 01:15:56 -0700 (PDT) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Tue, 22 Aug 2017 18:15:41 +1000 Message-Id: <20170822081543.30506-1-oohall@gmail.com> X-Mailer: git-send-email 2.9.5 Subject: [Skiboot] [PATCH 1/3] core/pci: Add for_each_pci_dev() 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: , Cc: alistair@popple.id.au MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Add an interation helper for PCI devices. This is functionally identical to the pci_walk_devs() helper function, but it allows us to write linear code rather than dropping us into the middle of callback hell. Signed-off-by: Oliver O'Halloran Reviewed-by: Alistair Popple --- core/pci.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/pci.h | 9 +++++++ 2 files changed, 93 insertions(+) diff --git a/core/pci.c b/core/pci.c index 4296180ad111..c5d2fba36508 100644 --- a/core/pci.c +++ b/core/pci.c @@ -1798,6 +1798,90 @@ static struct pci_device *__pci_walk_dev(struct phb *phb, return NULL; } +/* + * pci_next_dev(phb, prev, pass) - Iteration worker function + * + * phb - phb that we're iterating + * prev - the last pci_device returned by pci_next_dev + * + * pass - a cookie used to track the iteration state. See below if you + * really want to know the details. + */ +struct pci_device *pci_next_dev(struct phb *phb, struct pci_device *prev, + int *pass) +{ + struct pci_device *next, *last; + struct list_head *siblings; + + assert(phb); + + /* start of iteration */ + if (!prev) { + *pass = 0; + return list_top(&phb->devices, struct pci_device, link); + } + +up: + assert(prev); + + if (prev->parent) + siblings = &prev->parent->children; + else + siblings = &phb->devices; + + last = list_tail(siblings, struct pci_device, link); + assert(last); + + /* + * You made it this far so you get an explaination! + * + * We need to ensure that the iteration order is correct, that is we are + * supposed to look at each *device* on a bus before looking at the + * *child buses* below those devices, as is done in pci_walk_devs(). In + * other words, we do two pases of every bus. + * + * The 'pass' variable is used to track which pass we are on. When it's + * even we are just visiting each device and when odd we are descending + * into child buses if we find any. + */ + if (prev == last) { + if (*pass & 1) { /* end of the odd pass */ + if (!prev->parent) { + assert(*pass == 1); + return NULL; + } + + /* back to the odd pass across the parent's bus */ + (*pass) -= 2; + prev = prev->parent; + goto up; + } else { + next = list_top(siblings, struct pci_device, link); + (*pass)++; + } + } else { + next = list_entry(prev->link.next, struct pci_device, link); + } + + /* now find the device we should return */ + if (!(*pass & 1)) + return next; + + /* for an odd pass we scan for another child bus to descend into */ + while (list_empty(&next->children)) { + if (next == last) { + prev = last; + goto up; + } + + next = list_entry(next->link.next, struct pci_device, link); + } + + /* increment pass so it's even */ + (*pass)++; + return list_top(&next->children, struct pci_device, link); +} + struct pci_device *pci_walk_dev(struct phb *phb, struct pci_device *pd, int (*cb)(struct phb *, diff --git a/include/pci.h b/include/pci.h index 54a62fd19a99..81ad62f8fa19 100644 --- a/include/pci.h +++ b/include/pci.h @@ -460,6 +460,15 @@ static inline struct phb *__pci_next_phb_idx(uint64_t *phb_id) { for (uint64_t __phb_idx = 0; \ (phb = __pci_next_phb_idx(&__phb_idx)) ; ) + +struct pci_device *pci_next_dev(struct phb *phb, struct pci_device *pd, + int *pass); + +/* pass should be an int *, see pci_next_dev() for details */ +#define for_each_pci_dev(phb, pd, pass) \ + for (pd = pci_next_dev(phb, NULL, pass); pd; \ + pd = pci_next_dev(phb, pd, pass)) + /* Device tree */ extern void pci_std_swizzle_irq_map(struct dt_node *dt_node, struct pci_device *pd,