]> Git Repo - linux.git/commitdiff
Revert "powerpc/pci: unmap legacy INTx interrupts when a PHB is removed"
authorQian Cai <[email protected]>
Wed, 14 Oct 2020 18:28:11 +0000 (14:28 -0400)
committerMichael Ellerman <[email protected]>
Thu, 15 Oct 2020 02:42:49 +0000 (13:42 +1100)
This reverts commit 3a3181e16fbde752007759f8759d25e0ff1fc425 which
causes memory corruptions on POWER9 powernv. eg:

  pci_bus 0035:08: busn_res: [bus 08-0c] is released
  =============================================================================
  BUG kmalloc-16 (Tainted: G        W  O     ): Object already free
  -----------------------------------------------------------------------------
  Disabling lock debugging due to kernel taint
  INFO: Allocated in pcibios_scan_phb+0x104/0x3e0 age=1960714 cpu=4 pid=1
   __slab_alloc+0xa4/0xf0
   __kmalloc+0x294/0x330
   pcibios_scan_phb+0x104/0x3e0
   pcibios_init+0x84/0x124
   do_one_initcall+0xac/0x528
   kernel_init_freeable+0x35c/0x3fc
   kernel_init+0x24/0x148
   ret_from_kernel_thread+0x5c/0x80
  INFO: Freed in pcibios_remove_bus+0x70/0x90 age=0 cpu=16 pid=1717146
   kfree+0x49c/0x510
   pcibios_remove_bus+0x70/0x90
   pci_remove_bus+0xe4/0x110
   pci_remove_bus_device+0x74/0x170
   pci_remove_bus_device+0x4c/0x170
   pci_stop_and_remove_bus_device_locked+0x34/0x50
   remove_store+0xc0/0xe0
   dev_attr_store+0x30/0x50
   sysfs_kf_write+0x68/0xb0
   kernfs_fop_write+0x114/0x260
   vfs_write+0xe4/0x260
   ksys_write+0x74/0x130
   system_call_exception+0xf8/0x1d0
   system_call_common+0xe8/0x218
  INFO: Slab 0x0000000099caaf22 objects=178 used=174 fp=0x00000000006a64b0 flags=0x7fff8000000201
  INFO: Object 0x00000000f360132d @offset=30192 fp=0x0000000000000000

Signed-off-by: Qian Cai <[email protected]>
Acked-by: Oliver O'Halloran <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
arch/powerpc/include/asm/pci-bridge.h
arch/powerpc/kernel/pci-common.c

index d21e070352dcad081d14848db76f5fa5a7ae0715..d2a2a14e56f91e07b7c4b673030f7f60e4be406b 100644 (file)
@@ -48,9 +48,6 @@ struct pci_controller_ops {
 
 /*
  * Structure of a PCI controller (host bridge)
- *
- * @irq_count: number of interrupt mappings
- * @irq_map: interrupt mappings
  */
 struct pci_controller {
        struct pci_bus *bus;
@@ -130,9 +127,6 @@ struct pci_controller {
 
        void *private_data;
        struct npu *npu;
-
-       unsigned int irq_count;
-       unsigned int *irq_map;
 };
 
 /* These are used for config access before all the PCI probing
index deb831f0ae1346d9c091a0133cf60fb38ec2de90..be108616a721fbf594b717798d615ad503ea9a30 100644 (file)
@@ -353,115 +353,6 @@ struct pci_controller *pci_find_controller_for_domain(int domain_nr)
        return NULL;
 }
 
-/*
- * Assumption is made on the interrupt parent. All interrupt-map
- * entries are considered to have the same parent.
- */
-static int pcibios_irq_map_count(struct pci_controller *phb)
-{
-       const __be32 *imap;
-       int imaplen;
-       struct device_node *parent;
-       u32 intsize, addrsize, parintsize, paraddrsize;
-
-       if (of_property_read_u32(phb->dn, "#interrupt-cells", &intsize))
-               return 0;
-       if (of_property_read_u32(phb->dn, "#address-cells", &addrsize))
-               return 0;
-
-       imap = of_get_property(phb->dn, "interrupt-map", &imaplen);
-       if (!imap) {
-               pr_debug("%pOF : no interrupt-map\n", phb->dn);
-               return 0;
-       }
-       imaplen /= sizeof(u32);
-       pr_debug("%pOF : imaplen=%d\n", phb->dn, imaplen);
-
-       if (imaplen < (addrsize + intsize + 1))
-               return 0;
-
-       imap += intsize + addrsize;
-       parent = of_find_node_by_phandle(be32_to_cpup(imap));
-       if (!parent) {
-               pr_debug("%pOF : no imap parent found !\n", phb->dn);
-               return 0;
-       }
-
-       if (of_property_read_u32(parent, "#interrupt-cells", &parintsize)) {
-               pr_debug("%pOF : parent lacks #interrupt-cells!\n", phb->dn);
-               return 0;
-       }
-
-       if (of_property_read_u32(parent, "#address-cells", &paraddrsize))
-               paraddrsize = 0;
-
-       return imaplen / (addrsize + intsize + 1 + paraddrsize + parintsize);
-}
-
-static void pcibios_irq_map_init(struct pci_controller *phb)
-{
-       phb->irq_count = pcibios_irq_map_count(phb);
-       if (phb->irq_count < PCI_NUM_INTX)
-               phb->irq_count = PCI_NUM_INTX;
-
-       pr_debug("%pOF : interrupt map #%d\n", phb->dn, phb->irq_count);
-
-       phb->irq_map = kcalloc(phb->irq_count, sizeof(unsigned int),
-                              GFP_KERNEL);
-}
-
-static void pci_irq_map_register(struct pci_dev *pdev, unsigned int virq)
-{
-       struct pci_controller *phb = pci_bus_to_host(pdev->bus);
-       int i;
-
-       if (!phb->irq_map)
-               return;
-
-       for (i = 0; i < phb->irq_count; i++) {
-               /*
-                * Look for an empty or an equivalent slot, as INTx
-                * interrupts can be shared between adapters.
-                */
-               if (phb->irq_map[i] == virq || !phb->irq_map[i]) {
-                       phb->irq_map[i] = virq;
-                       break;
-               }
-       }
-
-       if (i == phb->irq_count)
-               pr_err("PCI:%s all platform interrupts mapped\n",
-                      pci_name(pdev));
-}
-
-/*
- * Clearing the mapped interrupts will also clear the underlying
- * mappings of the ESB pages of the interrupts when under XIVE. It is
- * a requirement of PowerVM to clear all memory mappings before
- * removing a PHB.
- */
-static void pci_irq_map_dispose(struct pci_bus *bus)
-{
-       struct pci_controller *phb = pci_bus_to_host(bus);
-       int i;
-
-       if (!phb->irq_map)
-               return;
-
-       pr_debug("PCI: Clearing interrupt mappings for PHB %04x:%02x...\n",
-                pci_domain_nr(bus), bus->number);
-       for (i = 0; i < phb->irq_count; i++)
-               irq_dispose_mapping(phb->irq_map[i]);
-
-       kfree(phb->irq_map);
-}
-
-void pcibios_remove_bus(struct pci_bus *bus)
-{
-       pci_irq_map_dispose(bus);
-}
-EXPORT_SYMBOL_GPL(pcibios_remove_bus);
-
 /*
  * Reads the interrupt pin to determine if interrupt is use by card.
  * If the interrupt is used, then gets the interrupt line from the
@@ -510,8 +401,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
 
        pci_dev->irq = virq;
 
-       /* Record all interrut mappings for later removal of a PHB */
-       pci_irq_map_register(pci_dev, virq);
        return 0;
 }
 
@@ -1665,9 +1554,6 @@ void pcibios_scan_phb(struct pci_controller *hose)
 
        pr_debug("PCI: Scanning PHB %pOF\n", node);
 
-       /* Allocate interrupt mappings array */
-       pcibios_irq_map_init(hose);
-
        /* Get some IO space for the new PHB */
        pcibios_setup_phb_io_space(hose);
 
This page took 0.079895 seconds and 4 git commands to generate.