From patchwork Wed May 28 22:29:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Duyck, Alexander H" X-Patchwork-Id: 4257701 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: X-Original-To: patchwork-linux-pci@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AD885BF90B for ; Wed, 28 May 2014 22:29:18 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E2E4A20304 for ; Wed, 28 May 2014 22:29:17 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 085CA202E5 for ; Wed, 28 May 2014 22:29:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755808AbaE1W3Q (ORCPT ); Wed, 28 May 2014 18:29:16 -0400 Received: from mga02.intel.com ([134.134.136.20]:54605 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755804AbaE1W3P (ORCPT ); Wed, 28 May 2014 18:29:15 -0400 Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 28 May 2014 15:29:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.98,930,1392192000"; d="scan'208";a="519301463" Received: from ahduyck-cp2.jf.intel.com ([10.23.155.181]) by orsmga001.jf.intel.com with ESMTP; 28 May 2014 15:29:09 -0700 Subject: [PATCH 1/2] pci: Add pci_walk_vbus for walking virtual busses associated with SR-IOV From: Alexander Duyck To: bhelgaas@google.com, ddutile@redhat.com Cc: linux-pci@vger.kernel.org, alex.williamson@redhat.com, linux-kernel@vger.kernel.org Date: Wed, 28 May 2014 15:29:09 -0700 Message-ID: <20140528222901.18898.48031.stgit@ahduyck-cp2.jf.intel.com> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This function provides a simple means for applying a given function to all devices on bus and all of it's children, including virtual busses. To do this the function begins by processing all devices on the bus, then it will proceed through bus->children and process each of the child busses. Signed-off-by: Alexander Duyck --- drivers/pci/bus.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 2 ++ 2 files changed, 46 insertions(+), 0 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-pci" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index fb8aed3..769bbcb 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -336,6 +336,50 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), } EXPORT_SYMBOL_GPL(pci_walk_bus); +/** pci_walk_vbus - walk devices on/under bus, calling callback. + * @top bus whose devices should be walked + * @cb callback to be called for each device found + * @userdata arbitrary pointer to be passed to callback. + * + * Walk the given bus, including any child buses under this bus. + * Call the provided callback on each device found. + * + * We check the return of @cb each time. If it returns anything + * other than 0, we break out. + * + */ +void pci_walk_vbus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), + void *userdata) +{ + struct list_head *bus_next; + struct pci_bus *bus; + struct pci_dev *dev; + + down_read(&pci_bus_sem); + bus_next = &top->node; + for (;;) { + /* prep bus for next iteration */ + bus = list_entry(bus_next, struct pci_bus, node); + + /* process each device on this bus */ + list_for_each_entry(dev, &bus->devices, bus_list) { + if (cb(dev, userdata)) + goto release_semaphore; + } + + /* end of this bus, go to child, next bus, or finish */ + for (bus_next = bus->children.next; + bus_next == &bus->children; + bus_next = bus->node.next, bus = bus->parent) { + if (bus == top) + goto release_semaphore; + } + } +release_semaphore: + up_read(&pci_bus_sem); +} +EXPORT_SYMBOL_GPL(pci_walk_vbus); + struct pci_bus *pci_bus_get(struct pci_bus *bus) { if (bus) diff --git a/include/linux/pci.h b/include/linux/pci.h index aab57b4..1fb18a8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1118,6 +1118,8 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata); +void pci_walk_vbus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), + void *userdata); int pci_cfg_space_size(struct pci_dev *dev); unsigned char pci_bus_max_busnr(struct pci_bus *bus); void pci_setup_bridge(struct pci_bus *bus);