From patchwork Wed May 23 22:37:00 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bjorn Helgaas X-Patchwork-Id: 161040 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 6E270B7025 for ; Thu, 24 May 2012 08:37:05 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751916Ab2EWWhD (ORCPT ); Wed, 23 May 2012 18:37:03 -0400 Received: from mail-qa0-f74.google.com ([209.85.216.74]:59975 "EHLO mail-qa0-f74.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751656Ab2EWWhC (ORCPT ); Wed, 23 May 2012 18:37:02 -0400 Received: by qabg24 with SMTP id g24so601331qab.1 for ; Wed, 23 May 2012 15:37:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=subject:to:from:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding; bh=1yF1FFn0OZjOUacVLJTveXRLOrhbwHtTEU/9sHGVOz4=; b=YjUfPdhZB8IDRmsGhUQcBjOCm20shVdHUW/ng7FaaODtW+eHzYdUwQiJ2m/1qAsjJW GsQQpPFTC10VsgiXdMhdF2d3x616DsdL+snJsU/NW9gAzR0hz6zT/n4OkbrZv8tGX2Ej VWhBHFoyAwGSND9HhdzcuwtHQOXVoE/ZLCoF8LkL5QUn3SBF51PlCMxQ1NtzWuu1vSuv tdlILTWVEY76GwD3loZC166NN9P3Rx6DjMk1/BSr3KLbL6yQOl0meG2GcuOY1vJyp3UU DDmWL85bMm0aIc3d3pG8vTECKBvhs7lSJON2Fmsu/FPfokxWMZnEBVgZ6c5LHRsbwLPY zuig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=subject:to:from:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=1yF1FFn0OZjOUacVLJTveXRLOrhbwHtTEU/9sHGVOz4=; b=fnNL9wrL0bOeCxrhSHVcaIVhUmJBkucuRxjWXxKhGx2JYLB5AEHdwUVZqywUJKRmU/ OVvK3l5Lqnfkg+z1PiRVdy05cBnrE0LRHlO1WemHI3RZcwXfKaeraOPsRHcUVTZF8xxL s3h8jV5yPHaRCmf+gEdMfFb90480EEzLaiDGjMuyLM0T8JsUejacBl595szVJqdX/kiF a9OKL3FKNDE6vtfdyWOOZBa7nYP9r6p1ewk9fTfo/sZleRepyECjV6jhfrBKf+/ML7/e dsLUfd1jUZT5BaFwXRuslnxiIZBLrGsUso2CMXaBa+FQd6xAkWFJOggAUnH5CErmFxBy 5Ubw== Received: by 10.101.46.13 with SMTP id y13mr11337453anj.22.1337812621312; Wed, 23 May 2012 15:37:01 -0700 (PDT) Received: by 10.101.46.13 with SMTP id y13mr11337437anj.22.1337812621204; Wed, 23 May 2012 15:37:01 -0700 (PDT) Received: from wpzn4.hot.corp.google.com (216-239-44-65.google.com [216.239.44.65]) by gmr-mx.google.com with ESMTPS id b73si154877yhh.4.2012.05.23.15.37.01 (version=TLSv1/SSLv3 cipher=AES128-SHA); Wed, 23 May 2012 15:37:01 -0700 (PDT) Received: from bhelgaas.mtv.corp.google.com (bhelgaas.mtv.corp.google.com [172.18.96.155]) by wpzn4.hot.corp.google.com (Postfix) with ESMTP id 0D0251E0290; Wed, 23 May 2012 15:37:01 -0700 (PDT) Received: from bhelgaas.mtv.corp.google.com (unknown [IPv6:::1]) by bhelgaas.mtv.corp.google.com (Postfix) with ESMTP id B4DD818016D; Wed, 23 May 2012 15:37:00 -0700 (PDT) Subject: [PATCH v3 1/2] powerpc/PCI: move DMA & IRQ init to device_add() notification path To: Hiroo Matsumoto From: Bjorn Helgaas Cc: Michal Simek , benh@kernel.crashing.org, microblaze-uclinux@itee.uq.edu.au, linux-pci@vger.kernel.org, Jesse Larrew , jbarnes@virtuousgeek.org, Dominik Brodowski , Kenji Kaneshige , linuxppc-dev@lists.ozlabs.org Date: Wed, 23 May 2012 16:37:00 -0600 Message-ID: <20120523223700.24276.76804.stgit@bhelgaas.mtv.corp.google.com> In-Reply-To: <20120523222635.24276.80023.stgit@bhelgaas.mtv.corp.google.com> References: <20120523222635.24276.80023.stgit@bhelgaas.mtv.corp.google.com> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Gm-Message-State: ALoCoQnO2WeF2ySdxUb9hifdzFRatRbDf5gsivujvFknxqLsygU/Apjnd17OhOtewSjgozf2erCQCGcVCzfXgKpUoMv4tvyy3+gZhPpZIV7Ich4TSIkZltptPpM7VPcHRjIQBfYahXvnkMjlTvA9K/pN8tnGs2knEQ== Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org From: Hiroo Matsumoto PowerPC initialized DMA and IRQ information in the pci_scan_child_bus() -> pcibios_fixup_bus() path. Some hotplug drivers use that path, but others don't, e.g., pciehp, so sometimes hot-added devices are only partly initialized. This patch moves that initialization from pcibios_fixup_bus() to a new pci_bus_notify() called in the pci_bus_add_device() -> device_add() path. That means the initialization happens the same way for all PCI devices, whether they are present at boot or hot-added later. Note that powerpc was the only user of pci_fixup_cardbus(), which was used to do this same setup for cardbus devices. That's no longer needed because this setup will now be done in the same device_add() notification path as all other PCI devices. Typical failure of a hot-added e1000e device prior to this change: # echo 1 > /sys/bus/pci/slots/1/power e1000e 0000:03:00.0: enabling device (0000 -> 0002) e1000e 0000:03:00.0: No usable DMA configuration, aborting e1000e: probe of 0000:03:00.0 failed with error -5 Successful initialization after this change: # echo 1 > /sys/bus/pci/slots/1/power e1000e 0000:03:00.0: enabling device (0000 -> 0002) irq: irq 6 on host /soc@ffe00000/msi@41600 mapped to virtual irq 27 e1000e 0000:03:00.0: eth0: (PCI Express:2.5GT/s:Width x1) 00:15:17:bf:c0:c9 e1000e 0000:03:00.0: eth0: Intel(R) PRO/1000 Network Connection e1000e 0000:03:00.0: eth0: MAC: 1, PHY: 4, PBA No: D50861-003 [bhelgaas: changelog, notifier name, registration can be __init] CC: Dominik Brodowski Signed-off-by: Hiroo MATSUMOTO Signed-off-by: Bjorn Helgaas --- arch/powerpc/include/asm/pci.h | 2 - arch/powerpc/kernel/pci-common.c | 87 ++++++++++++++-------------- arch/powerpc/kernel/pci_32.c | 2 + arch/powerpc/kernel/pci_64.c | 2 + arch/powerpc/kernel/pci_of_scan.c | 1 arch/powerpc/platforms/pseries/pci_dlpar.c | 1 drivers/pci/pci.c | 5 -- drivers/pcmcia/cardbus.c | 3 - include/linux/pci.h | 3 - 9 files changed, 49 insertions(+), 57 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/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h index 6653f27..d6a36a4 100644 --- a/arch/powerpc/include/asm/pci.h +++ b/arch/powerpc/include/asm/pci.h @@ -183,10 +183,10 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar, resource_size_t *start, resource_size_t *end); extern resource_size_t pcibios_io_space_offset(struct pci_controller *hose); -extern void pcibios_setup_bus_devices(struct pci_bus *bus); extern void pcibios_setup_bus_self(struct pci_bus *bus); extern void pcibios_setup_phb_io_space(struct pci_controller *hose); extern void pcibios_scan_phb(struct pci_controller *hose); +extern void pcibios_setup_bus_notifier(void); #endif /* __KERNEL__ */ #endif /* __ASM_POWERPC_PCI_H */ diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 7320f36..41b39ba 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1009,40 +1009,6 @@ void __devinit pcibios_setup_bus_self(struct pci_bus *bus) ppc_md.pci_dma_bus_setup(bus); } -void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) -{ - struct pci_dev *dev; - - pr_debug("PCI: Fixup bus devices %d (%s)\n", - bus->number, bus->self ? pci_name(bus->self) : "PHB"); - - list_for_each_entry(dev, &bus->devices, bus_list) { - /* Cardbus can call us to add new devices to a bus, so ignore - * those who are already fully discovered - */ - if (dev->is_added) - continue; - - /* Fixup NUMA node as it may not be setup yet by the generic - * code and is needed by the DMA init - */ - set_dev_node(&dev->dev, pcibus_to_node(dev->bus)); - - /* Hook up default DMA ops */ - set_dma_ops(&dev->dev, pci_dma_ops); - set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); - - /* Additional platform DMA/iommu setup */ - if (ppc_md.pci_dma_dev_setup) - ppc_md.pci_dma_dev_setup(dev); - - /* Read default IRQs and fixup if necessary */ - pci_read_irq_line(dev); - if (ppc_md.pci_irq_fixup) - ppc_md.pci_irq_fixup(dev); - } -} - void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ @@ -1059,19 +1025,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) /* Now fixup the bus bus */ pcibios_setup_bus_self(bus); - - /* Now fixup devices on that bus */ - pcibios_setup_bus_devices(bus); } EXPORT_SYMBOL(pcibios_fixup_bus); -void __devinit pci_fixup_cardbus(struct pci_bus *bus) -{ - /* Now fixup devices on that bus */ - pcibios_setup_bus_devices(bus); -} - - static int skip_isa_ioresource_align(struct pci_dev *dev) { if (pci_has_flag(PCI_CAN_SKIP_ISA_ALIGN) && @@ -1685,6 +1641,49 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) } } +static int pci_bus_notify(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct pci_dev *dev = to_pci_dev(data); + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + /* Setup OF node pointer in the device */ + dev->dev.of_node = pci_device_to_OF_node(dev); + + /* Fixup NUMA node as it may not be setup yet by the generic + * code and is needed by the DMA init + */ + set_dev_node(&dev->dev, pcibus_to_node(dev->bus)); + + /* Hook up default DMA ops */ + set_dma_ops(&dev->dev, pci_dma_ops); + set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); + + /* Additional platform DMA/iommu setup */ + if (ppc_md.pci_dma_dev_setup) + ppc_md.pci_dma_dev_setup(dev); + + /* Read default IRQs and fixup if necessary */ + pci_read_irq_line(dev); + if (ppc_md.pci_irq_fixup) + ppc_md.pci_irq_fixup(dev); + + break; + } + + return 0; +} + +static struct notifier_block device_nb = { + .notifier_call = pci_bus_notify, +}; + +void __init pcibios_setup_bus_notifier(void) +{ + bus_register_notifier(&pci_bus_type, &device_nb); +} + static void fixup_hide_host_resource_fsl(struct pci_dev *dev) { int i, class = dev->class >> 8; diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 4b06ec5..640cc35 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -231,6 +231,8 @@ static int __init pcibios_init(void) printk(KERN_INFO "PCI: Probing PCI hardware\n"); + pcibios_setup_bus_notifier(); + if (pci_has_flag(PCI_REASSIGN_ALL_BUS)) pci_assign_all_buses = 1; diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 4ff190f..8b212d3 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -48,6 +48,8 @@ static int __init pcibios_init(void) printk(KERN_INFO "PCI: Probing PCI hardware\n"); + pcibios_setup_bus_notifier(); + /* For now, override phys_mem_access_prot. If we need it,g * later, we may move that initialization to each ppc_md */ diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index ae5ea5e..eb09eca 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -333,7 +333,6 @@ static void __devinit __of_scan_bus(struct device_node *node, */ if (!rescan_existing) pcibios_setup_bus_self(bus); - pcibios_setup_bus_devices(bus); /* Now scan child busses */ list_for_each_entry(dev, &bus->devices, bus_list) { diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 3ccebc8..0b1b6b3 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -120,7 +120,6 @@ void pcibios_add_pci_devices(struct pci_bus * bus) num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); if (!num) return; - pcibios_setup_bus_devices(bus); max = bus->busn_res.start; for (pass=0; pass < 2; pass++) list_for_each_entry(dev, &bus->devices, bus_list) { diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 15d442a..43e0a4f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3789,11 +3789,6 @@ int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev) return 1; } -void __weak pci_fixup_cardbus(struct pci_bus *bus) -{ -} -EXPORT_SYMBOL(pci_fixup_cardbus); - static int __init pci_setup(char *str) { while (str) { diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 24caeaf..a980691 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -71,7 +71,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) unsigned int max, pass; s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); - pci_fixup_cardbus(bus); max = bus->busn_res.start; for (pass = 0; pass < 2; pass++) @@ -85,7 +84,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) */ pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - cardbus_config_irq_and_cls(bus, s->pci_irq); /* socket specific tune function */ if (s->tune_bridge) @@ -93,6 +91,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) pci_enable_bridges(bus); pci_bus_add_devices(bus); + cardbus_config_irq_and_cls(bus, s->pci_irq); return 0; } diff --git a/include/linux/pci.h b/include/linux/pci.h index a0e2d7f..3924c02 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -651,9 +651,6 @@ resource_size_t pcibios_align_resource(void *, const struct resource *, resource_size_t); void pcibios_update_irq(struct pci_dev *, int irq); -/* Weak but can be overriden by arch */ -void pci_fixup_cardbus(struct pci_bus *); - /* Generic PCI functions used internally */ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,