Commit aa8032b6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pci-v3.11-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci

Pull PCI fixes from Bjorn Helgaas:
 "Yinghai fixed a couple regressions: one resource assignment problem
  introduced in v3.10 that showed up with SR-IOV on powerpc, and another
  SR-IOV hot-remove issue related to refcounting changes we merged for
  v3.11.

  Yinghai is still working on another SR-IOV-related fix or two, which
  will be simpler if pciehp is non-modular, so I included the Kconfig
  changes now to get them in earlier.

  Finally, a minor fix for the ARM Marvell EBU host bridge driver that
  was merged for v3.11

  Hotplug:
      PCI: pciehp: Fix null pointer deref when hot-removing SR-IOV device
      PCI: hotplug: Convert to be builtin only, not modular
      PCI: pciehp: Convert pciehp to be builtin only, not modular

  Resource allocation:
      PCI: Retry allocation of only the resource type that failed

  ARM:
      PCI: mvebu: Disable prefetchable memory support in PCI-to-PCI bridge"

* tag 'pci-v3.11-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci:
  PCI: mvebu: Disable prefetchable memory support in PCI-to-PCI bridge
  PCI: Retry allocation of only the resource type that failed
  PCI: pciehp: Convert pciehp to be builtin only, not modular
  PCI: hotplug: Convert to be builtin only, not modular
  PCI: pciehp: Fix null pointer deref when hot-removing SR-IOV device
parents 1fe0135b 36dd1f3e
......@@ -31,7 +31,7 @@ CONFIG_ACPI_FAN=m
CONFIG_ACPI_DOCK=y
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_CONTAINER=m
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=m
CONFIG_PACKET=y
CONFIG_UNIX=y
......
......@@ -25,7 +25,7 @@ CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_CONTAINER=m
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=m
CONFIG_PACKET=y
CONFIG_UNIX=y
......
......@@ -31,7 +31,7 @@ CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_CONTAINER=m
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=m
CONFIG_PACKET=y
CONFIG_UNIX=y
......
......@@ -32,7 +32,7 @@ CONFIG_ACPI_BUTTON=m
CONFIG_ACPI_FAN=m
CONFIG_ACPI_PROCESSOR=m
CONFIG_ACPI_CONTAINER=m
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_ACPI=m
CONFIG_PACKET=y
CONFIG_UNIX=y
......
......@@ -58,7 +58,7 @@ CONFIG_SCHED_SMT=y
CONFIG_PPC_DENORMALISATION=y
CONFIG_PCCARD=y
CONFIG_ELECTRA_CF=y
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_RPA=m
CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
CONFIG_PACKET=y
......
......@@ -32,7 +32,7 @@ CONFIG_IRQ_ALL_CPUS=y
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_PCI_MSI=y
CONFIG_PCCARD=y
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=m
......
......@@ -53,7 +53,7 @@ CONFIG_PPC_64K_PAGES=y
CONFIG_PPC_SUBPAGE_PROT=y
CONFIG_SCHED_SMT=y
CONFIG_PPC_DENORMALISATION=y
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_HOTPLUG_PCI_RPA=m
CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
CONFIG_PACKET=y
......
......@@ -22,7 +22,7 @@ CONFIG_PREEMPT=y
CONFIG_CMDLINE_OVERWRITE=y
CONFIG_CMDLINE="console=ttySC1,115200 mem=64M root=/dev/nfs"
CONFIG_PCI=y
CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI=y
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_PACKET=y
......
......@@ -86,10 +86,6 @@ struct mvebu_sw_pci_bridge {
u16 secondary_status;
u16 membase;
u16 memlimit;
u16 prefmembase;
u16 prefmemlimit;
u32 prefbaseupper;
u32 preflimitupper;
u16 iobaseupper;
u16 iolimitupper;
u8 cappointer;
......@@ -419,15 +415,7 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
break;
case PCI_PREF_MEMORY_BASE:
*value = (bridge->prefmemlimit << 16 | bridge->prefmembase);
break;
case PCI_PREF_BASE_UPPER32:
*value = bridge->prefbaseupper;
break;
case PCI_PREF_LIMIT_UPPER32:
*value = bridge->preflimitupper;
*value = 0;
break;
case PCI_IO_BASE_UPPER16:
......@@ -501,19 +489,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
mvebu_pcie_handle_membase_change(port);
break;
case PCI_PREF_MEMORY_BASE:
bridge->prefmembase = value & 0xffff;
bridge->prefmemlimit = value >> 16;
break;
case PCI_PREF_BASE_UPPER32:
bridge->prefbaseupper = value;
break;
case PCI_PREF_LIMIT_UPPER32:
bridge->preflimitupper = value;
break;
case PCI_IO_BASE_UPPER16:
bridge->iobaseupper = value & 0xffff;
bridge->iolimitupper = value >> 16;
......
......@@ -3,16 +3,13 @@
#
menuconfig HOTPLUG_PCI
tristate "Support for PCI Hotplug"
bool "Support for PCI Hotplug"
depends on PCI && SYSFS
---help---
Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is
powered up and running.
To compile this driver as a module, choose M here: the
module will be called pci_hotplug.
When in doubt, say N.
if HOTPLUG_PCI
......
......@@ -92,7 +92,14 @@ int pciehp_unconfigure_device(struct slot *p_slot)
if (ret)
presence = 0;
list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
/*
* Stopping an SR-IOV PF device removes all the associated VFs,
* which will update the bus->devices list and confuse the
* iterator. Therefore, iterate in reverse so we remove the VFs
* first, then the PF. We do the same in pci_stop_bus_device().
*/
list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
bus_list) {
pci_dev_get(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
......
......@@ -14,15 +14,12 @@ config PCIEPORTBUS
# Include service Kconfig here
#
config HOTPLUG_PCI_PCIE
tristate "PCI Express Hotplug driver"
bool "PCI Express Hotplug driver"
depends on HOTPLUG_PCI && PCIEPORTBUS
help
Say Y here if you have a motherboard that supports PCI Express Native
Hotplug
To compile this driver as a module, choose M here: the
module will be called pciehp.
When in doubt, say N.
source "drivers/pci/pcie/aer/Kconfig"
......
......@@ -300,6 +300,47 @@ static void assign_requested_resources_sorted(struct list_head *head,
}
}
static unsigned long pci_fail_res_type_mask(struct list_head *fail_head)
{
struct pci_dev_resource *fail_res;
unsigned long mask = 0;
/* check failed type */
list_for_each_entry(fail_res, fail_head, list)
mask |= fail_res->flags;
/*
* one pref failed resource will set IORESOURCE_MEM,
* as we can allocate pref in non-pref range.
* Will release all assigned non-pref sibling resources
* according to that bit.
*/
return mask & (IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH);
}
static bool pci_need_to_release(unsigned long mask, struct resource *res)
{
if (res->flags & IORESOURCE_IO)
return !!(mask & IORESOURCE_IO);
/* check pref at first */
if (res->flags & IORESOURCE_PREFETCH) {
if (mask & IORESOURCE_PREFETCH)
return true;
/* count pref if its parent is non-pref */
else if ((mask & IORESOURCE_MEM) &&
!(res->parent->flags & IORESOURCE_PREFETCH))
return true;
else
return false;
}
if (res->flags & IORESOURCE_MEM)
return !!(mask & IORESOURCE_MEM);
return false; /* should not get here */
}
static void __assign_resources_sorted(struct list_head *head,
struct list_head *realloc_head,
struct list_head *fail_head)
......@@ -312,11 +353,24 @@ static void __assign_resources_sorted(struct list_head *head,
* if could do that, could get out early.
* if could not do that, we still try to assign requested at first,
* then try to reassign add_size for some resources.
*
* Separate three resource type checking if we need to release
* assigned resource after requested + add_size try.
* 1. if there is io port assign fail, will release assigned
* io port.
* 2. if there is pref mmio assign fail, release assigned
* pref mmio.
* if assigned pref mmio's parent is non-pref mmio and there
* is non-pref mmio assign fail, will release that assigned
* pref mmio.
* 3. if there is non-pref mmio assign fail or pref mmio
* assigned fail, will release assigned non-pref mmio.
*/
LIST_HEAD(save_head);
LIST_HEAD(local_fail_head);
struct pci_dev_resource *save_res;
struct pci_dev_resource *dev_res;
struct pci_dev_resource *dev_res, *tmp_res;
unsigned long fail_type;
/* Check if optional add_size is there */
if (!realloc_head || list_empty(realloc_head))
......@@ -348,6 +402,19 @@ static void __assign_resources_sorted(struct list_head *head,
return;
}
/* check failed type */
fail_type = pci_fail_res_type_mask(&local_fail_head);
/* remove not need to be released assigned res from head list etc */
list_for_each_entry_safe(dev_res, tmp_res, head, list)
if (dev_res->res->parent &&
!pci_need_to_release(fail_type, dev_res->res)) {
/* remove it from realloc_head list */
remove_from_list(realloc_head, dev_res->res);
remove_from_list(&save_head, dev_res->res);
list_del(&dev_res->list);
kfree(dev_res);
}
free_list(&local_fail_head);
/* Release assigned resource */
list_for_each_entry(dev_res, head, list)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment